最小割+强连通分量 COGS 426 血帆海盗
最小割定理我虽然说不太准,但大概就这个意思:对求完最大流后的残图进行tarjin,如果一条边的起点和终点不属于一个强连通分量,则这条边属于最大流。
联系一下,直接A
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define inf 10000000 #include<queue> using namespace std; int n,m,S=0,T,e,s,adj[100200],dep[100200]; int zhan[100005],inzhan[100005],dfn[100005],low[100005],tot,head,cnt; int belong[100005],vis[100005]; struct node { int u,v,l,next; } a[400005]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } void add(int u,int v,int l) { a[e].l=l;a[e].v=v;a[e].u=u;a[e].next=adj[u];adj[u]=e++; } int bfs() { memset(dep,0,sizeof(dep)); queue<int> q; q.push(S); dep[S]=1; while(!q.empty()) { int x=q.front();q.pop(); for(int i=adj[x];i!=-1;i=a[i].next) { int to=a[i].v; if(!dep[to]&&a[i].l) { dep[to]=dep[x]+1; q.push(to); if(to==T)return 1; } } } return 0; } int dfs(int x,int len) { int tmp=len,k; if(x==T)return len; for(int i=adj[x];i!=-1;i=a[i].next) { int to=a[i].v; if(dep[to]==dep[x]+1&&a[i].l&&tmp) { k=dfs(to,min(a[i].l,tmp)); if(!k) { dep[to]=0; continue; } a[i].l-=k; a[i^1].l+=k; tmp-=k; } } return len-tmp; } void tarjin(int x) { //vis[x]=1; zhan[++head]=x;inzhan[x]=1; dfn[x]=low[x]=++tot; for(int i=adj[x];i!=-1;i=a[i].next) if(a[i].l&&inzhan[a[i].v]<2) { int to=a[i].v; if(!inzhan[to]) { tarjin(to); low[x]=min(low[x],low[to]); } else if(inzhan[a[i].v]==1) low[x]=min(low[x],dfn[a[i].v]); } if(dfn[x]==low[x]) { cnt++; int tmp; while(1) { tmp=zhan[head--]; belong[tmp]=cnt; inzhan[tmp]=2; if(tmp==x)break; } } } int yjn() { freopen("sphere.in","r",stdin); freopen("sphere.out","w",stdout); scanf("%d%d",&n,&m); memset(adj,-1,sizeof(adj)); int x,y; for(int i=1;i<=m;i++) { x=read();y=read(); add(x,y,1); add(y,x,0); } T=n+1; for(int i=1;i<=n;i++) if(i<=n/2)add(S,i,1),add(i,S,0); else add(i,T,1),add(T,i,0); while(bfs())dfs(S,inf); for(int i=S;i<=T;i++)if(inzhan[i]<2)tarjin(i); s=0; for(int i=0;i<m;i++) if(a[i*2].l==0&&belong[a[i*2].u]!=belong[a[i*2].v]) s++; cout<<s; } int qty=yjn(); int main(){;}