當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
P6134-[JSOI2015]最小表示【bitset,拓扑排序】
生活随笔
收集整理的這篇文章主要介紹了
P6134-[JSOI2015]最小表示【bitset,拓扑排序】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P6134
題目大意
給出一張nnn個點mmm條邊的DAGDAGDAG。求聯通情況不變的情況下最多刪除幾條邊。
1≤n≤3×104,0≤M≤1051\leq n\leq 3\times 10^4,0\leq M\leq 10^51≤n≤3×104,0≤M≤105
解題思路
拓撲排序后,如果確定了后面若干個的最優解,那么不會影響到前面的決策,我們只需要對于每個點考慮刪除最多的出邊即可。
從后往前枚舉,對于一個點連接的集合EEE,按照拓撲序從小到大排后,每次加入一個點和它所有連接的點,如果該點已經聯通,那么這條邊就可以刪除了。
用bitsetbitsetbitset可以快速實現這個過程。
時間復雜度O(mnw)O(\frac{mn}{w})O(wmn?)
code
#include<cstdio> #include<cstring> #include<algorithm> #include<bitset> #include<queue> #include<vector> using namespace std; const int N=3e4+10; int n,m,cnt,tot,ans; int in[N],ls[N],top[N],tfn[N]; queue<int> q;vector<int> v; bitset<N> b[N]; struct node{int to,next; }a[N<<2]; void addl(int x,int y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;return; } void topsort(){for(int i=1;i<=n;i++)if(!in[i])q.push(i);while(!q.empty()){int x=q.front();q.pop();top[++cnt]=x;tfn[x]=cnt;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;in[y]--;if(!in[y])q.push(y);}}return; } bool cmp(int x,int y) {return tfn[x]<tfn[y];} int main() {scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);in[y]++;}topsort();for(int p=n;p>=1;p--){int x=top[p];v.clear();b[x][x]=1;for(int i=ls[x];i;i=a[i].next)v.push_back(a[i].to);sort(v.begin(),v.end(),cmp);for(int i=0;i<v.size();i++){int y=v[i];if(b[x][y]) ans++;else b[x]|=b[y];}}printf("%d\n",ans); }總結
以上是生活随笔為你收集整理的P6134-[JSOI2015]最小表示【bitset,拓扑排序】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样用路由器连接别人家的WiFi了如何用
- 下一篇: 苹果20年前开的商店苹果20年前开的商店