CodeForces - 1547G How Many Paths?(强联通缩点+拓扑)
生活随笔
收集整理的這篇文章主要介紹了
CodeForces - 1547G How Many Paths?(强联通缩点+拓扑)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一張有向圖,無重邊,有環,現在需要判斷每個點和點 111 的關系:
題目分析:直接強聯通縮點將原圖轉換成一個 DAGDAGDAG,然后直接拓撲就可以了,邊拓撲邊轉移 dpdpdp,也就是答案,dpdpdp 的方程自己分成 4?4=164*4=164?4=16 種情況討論一下,最后再合起來就可以了,不是很難
需要注意的是對于 ?1-1?1 的判斷和轉移
對于本題學到了一個很神奇的知識點,強聯通縮點后,序號的逆序就是拓撲序,這樣一來就不需要再記錄入度再開隊列拓撲了,非常的方便
代碼:
// Problem: G. How Many Paths? // Contest: Codeforces - Codeforces Round #731 (Div. 3) // URL: https://codeforces.com/contest/1547/problem/G // Memory Limit: 512 MB // Time Limit: 4000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100;const int M=1e6+100;struct Egde {int to,next; }edge1[M],edge2[M];int head1[N],head2[N],low[N],dfn[N],c[N],Stack[N],num,cnt,cnt2,cnt1,dcc,n,m,top,dp[N];bool ins[N],circle[N];vector<int>scc[N];void addedge1(int u,int v) {edge1[cnt1].to=v;edge1[cnt1].next=head1[u];head1[u]=cnt1++; }void addedge2(int u,int v) {edge2[cnt2].to=v;edge2[cnt2].next=head2[u];head2[u]=cnt2++; }void tarjan(int u) {dfn[u]=low[u]=++num;Stack[++top]=u;ins[u]=true;for(int i=head1[u];i!=-1;i=edge1[i].next){int v=edge1[i].to;if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(ins[v])low[u]=min(low[u],dfn[v]);}if(dfn[u]==low[u]){cnt++;int v;do{v=Stack[top--];ins[v]=false;c[v]=cnt;scc[cnt].push_back(v);}while(u!=v);} }void solve() {for(int i=1;i<=n;i++)//縮點 if(!dfn[i])tarjan(i); }void build()//縮點+連邊 {solve();for(int i=1;i<=n;i++){for(int j=head1[i];j!=-1;j=edge1[j].next){int u=i;int v=edge1[j].to;if(c[u]!=c[v])addedge2(c[u],c[v]);}} }void init(int n) {for(int i=0;i<=n;i++)scc[i].clear();top=cnt=cnt1=cnt2=num=dcc=0;memset(circle,false,n+5);memset(dp,0,sizeof(int)*(n+5));memset(head2,-1,sizeof(int)*(n+5));memset(head1,-1,sizeof(int)*(n+5));memset(low,0,sizeof(int)*(n+5));memset(dfn,0,sizeof(int)*(n+5));memset(c,0,sizeof(int)*(n+5));memset(ins,false,n+5); } void topo() {dp[c[1]]=1;for(int u=cnt;u>=1;u--) {if(dp[u]>0&&circle[u]) {dp[u]=-1;}if(dp[u]==0) {continue;}for(int i=head2[u];i!=-1;i=edge2[i].next) {int v=edge2[i].to;if(dp[v]==-1) {continue;}if(dp[u]==-1) {dp[v]=-1;} else if(dp[u]==1) {if(dp[v]==0) {dp[v]=1;} else if(dp[v]==1) {dp[v]=2;}} else if(dp[u]==2) {dp[v]=2;}}} } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int w;cin>>w;while(w--) {vector<pair<int,int>>node;read(n),read(m);init(n);while(m--) {int u,v;read(u),read(v);addedge1(u,v);node.push_back({u,v});}build();for(auto it:node) {int u=it.first,v=it.second;if(c[u]==c[v]) {circle[c[u]]=true;}}topo();for(int i=1;i<=n;i++) {printf("%d ",dp[c[i]]);}puts("");}return 0; } 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的CodeForces - 1547G How Many Paths?(强联通缩点+拓扑)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1547F A
- 下一篇: AcWing - 246. 区间最大公约