求最小割的可行边与必须边,先求一遍最大流,然后在残量网络上求强连通分量,对于可行边 起始点与结束点要在不同的强连通分量里,对于必须边 起始点要与S在一个SCC里 结束点要与T在一个SCC里。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #define M 1000009 10 #define EPS 1e-10 11 #define MO 10000 12 #define ll long long 13 using namespace std; 14 ll read() 15 { 16 char ch=getchar(); 17 ll x=0,f=1; 18 for(;ch<‘0‘||ch>‘9‘;ch=getchar()) 19 if(ch==‘-‘) 20 f=-1; 21 for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) 22 x=x*10+ch-‘0‘; 23 return x*f; 24 } 25 int dfn[M],low[M],T1,belong[M],sum,t,q[M],n,m,S,T,head[M],next[M],u[M],v[M],cnt=1,d[M],f[M],fr[M]; 26 void jia(int a1,int a2,int a3) 27 { 28 cnt++; 29 fr[cnt]=a1; 30 next[cnt]=head[a1]; 31 head[a1]=cnt; 32 u[cnt]=a2; 33 v[cnt]=a3; 34 } 35 bool bfs() 36 { 37 memset(d,0,sizeof(int)*(n+1)); 38 d[S]=1; 39 q[1]=S; 40 int h=0,t=1; 41 for(;h<t;) 42 { 43 int p=q[++h]; 44 for(int i=head[p];i;i=next[i]) 45 if(v[i]&&!d[u[i]]) 46 { 47 d[u[i]]=d[p]+1; 48 if(u[i]==T) 49 return 1; 50 q[++t]=u[i]; 51 } 52 } 53 return 0; 54 } 55 int dinic(int x,int f) 56 { 57 if(x==T) 58 return f; 59 int rest=f; 60 for(int i=head[x];i&&rest;i=next[i]) 61 if(v[i]&&d[u[i]]==d[x]+1) 62 { 63 int now=dinic(u[i],min(rest,v[i])); 64 if(!now) 65 d[u[i]]=0; 66 rest-=now; 67 v[i]-=now; 68 v[i^1]+=now; 69 } 70 return f-rest; 71 } 72 void tarjin(int x) 73 { 74 dfn[x]=low[x]=++T1; 75 q[++t]=x; 76 f[x]=1; 77 for(int i=head[x];i;i=next[i]) 78 if(v[i]) 79 { 80 if(!dfn[u[i]]) 81 { 82 tarjin(u[i]); 83 low[x]=min(low[x],low[u[i]]); 84 } 85 else if(f[u[i]]) 86 low[x]=min(low[x],dfn[u[i]]); 87 } 88 if(dfn[x]==low[x]) 89 { 90 sum++; 91 for(;q[t]!=x;t--) 92 { 93 belong[q[t]]=sum; 94 f[q[t]]=0; 95 } 96 belong[x]=sum; 97 f[x]=0; 98 t--; 99 } 100 } 101 int main() 102 { 103 n=read(); 104 m=read(); 105 S=read(); 106 T=read(); 107 for(int i=1;i<=m;i++) 108 { 109 int a1=read(),a2=read(),a3=read(); 110 jia(a1,a2,a3); 111 jia(a2,a1,0); 112 } 113 for(;bfs();) 114 dinic(S,0x7fffffff); 115 for(int i=1;i<=n;i++) 116 if(!dfn[i]) 117 tarjin(i); 118 for(int i=2;i<=cnt;i+=2) 119 if(v[i]) 120 printf("0 0\n"); 121 else 122 { 123 if(belong[fr[i]]==belong[u[i]]) 124 printf("0 "); 125 else 126 printf("1 "); 127 if(belong[fr[i]]==belong[S]&&belong[u[i]]==belong[T]) 128 printf("1\n"); 129 else 130 printf("0\n"); 131 } 132 return 0; 133 } 134
时间: 2024-10-13 21:34:53