题解:
其实这道题才是最裸的因为它把建图都交代了
相当于每个点出边唯一,入边唯一。
然后发现这是二分图匹配。
代码:
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 400 #define M 6050 const int inf = 0x3f3f3f3f; inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,hed[N],cur[N],cnt=-1,S,T; struct EG { int to,nxt; int w; }e[2*M]; void ae(int f,int t,int w) { e[++cnt].to = t; e[cnt].nxt = hed[f]; e[cnt].w = w; hed[f] = cnt; } int dep[N],fl[N]; int pre[N],fa[N]; bool vis[N]; queue<int>q; bool bfs() { memset(dep,0x3f,sizeof(dep)); memcpy(cur,hed,sizeof(cur)); dep[S] = 0,vis[S] = 1;q.push(S); while(!q.empty()) { int u = q.front(); q.pop(); for(int j=hed[u];~j;j=e[j].nxt) { int to = e[j].to; if(e[j].w&&dep[to]>dep[u]+1) { dep[to] = dep[u]+1; if(!vis[to]) { vis[to] = 1; q.push(to); } } } vis[u] = 0; } return dep[T]!=inf; } int dfs(int u,int lim) { if(u==T||!lim)return lim; int fl=0,f; for(int j=cur[u];~j;j=e[j].nxt) { cur[u] = j; int to = e[j].to; if(dep[to]==dep[u]+1&&(f=dfs(to,min(lim,e[j].w)))) { fl+=f,lim-=f; e[j].w-=f,e[j^1].w+=f; if(!lim)break; } } return fl; } int dinic() { int ret = 0; while(bfs()) ret+=dfs(S,inf); return ret; } bool use[N]; int findfa(int u) { for(int j=hed[u<<1|1];~j;j=e[j].nxt) { int to = e[j].to; if(to==T)continue; if(!e[j].w)continue; return findfa(to>>1); } return u; } void print(int u) { use[u] = 1; printf("%d ",u); for(int j=hed[u<<1];~j;j=e[j].nxt) { int to = e[j].to; if(to==S)continue; if(e[j].w)continue; print(to>>1); return ; } } int main() { n = rd(),m =rd(); S = 0,T = 1; memset(hed,-1,sizeof(hed)); for(int f,t,i=1;i<=m;i++) { f = rd(),t = rd(); ae(f<<1,t<<1|1,1); ae(t<<1|1,f<<1,0); } for(int i=1;i<=n;i++) { ae(S,i<<1,1); ae(i<<1,S,0); ae(i<<1|1,T,1); ae(T,i<<1|1,0); } int ans = n-dinic(); for(int i=1;i<=n;i++) { if(use[i])continue; int u = findfa(i); print(u); puts(""); } printf("%d ",ans); return 0; }