网络流24题2
https://loj.ac/problem/6001
wa了好几次是因为输出可行解的时候直接暴力搜连着原点还有容量的边然后直接输出,这样发现会少输出一些边,但是发现仪器是对的,这里我觉得是满流的边不一定是割,因此容量是0不能说明这个点不是可行解中的一个点,应该通过deep里的值来判断该点是否可达,如果可达说明与源点在同一个点集中,这是判断可行解的有力办法
#include <iostream> #include <cstring> #include <stdio.h> #include <queue> #include <algorithm> #include <vector> using namespace std; const int maxn = 2009; int yiqi[maxn]; int tot = 0; int head[maxn]; struct edge{ int v,nex,w; }e[maxn*2]; void addedge(int u,int v,int w){ e[tot] = (edge){v,head[u],w}; head[u] = tot++; e[tot] = (edge){u,head[v],0}; head[v] = tot++; } int deep[maxn]; bool bfs(int S,int T){ queue<int> q; memset(deep,0,sizeof(deep)); deep[S] = 1; q.push(S); while(!q.empty()){ int now = q.front(); q.pop(); for(int i=head[now];i!=-1;i=e[i].nex){ int v = e[i].v; int w = e[i].w; if(deep[v]!=0 || w<=0) continue; deep[v] = deep[now]+1; q.push(v); } } return deep[T]; } int dfs(int now,int T,int maxflow){ if(now==T) return maxflow; int all = 0; for(int i=head[now];i!=-1 && all<maxflow;i=e[i].nex){ int v = e[i].v; int w = e[i].w; if(deep[v]!=deep[now]+1 || w<=0) continue; int tt = dfs(v,T,min(maxflow-all,w)); e[i].w-=tt; e[i^1].w+=tt; all+=tt; } return all; } int dinic(int S,int T){ int ret = 0; while(bfs(S,T)){ ret+=dfs(S,T,0x3f3f3f3f); } return ret; } int main() { int n,m; scanf("%d%d",&m,&n); memset(head,-1,sizeof(head)); int all = 0; for(int i=1;i<=m;i++){ int t ; scanf("%d",&t); all+=t; char str; addedge(0,i,t); while(true){ str = getchar(); if(str=='\n' ||str=='\r'||str==EOF) break; int v; scanf("%d",&v); addedge(i,m+v,0x3f3f3f3f); } } for(int i=1;i<=n;i++){ int t; scanf("%d",&t); addedge(m+i,n+m+1,t); } int ans = dinic(0,n+m+1); vector<int> anspoint; for(int i=1;i<=m;i++){ if(deep[i]!=0){ anspoint.push_back(i); } } for(int i=0;i<anspoint.size();i++){ for(int j=head[anspoint[i]];j!=-1;j=e[j].nex){ int w = e[j].w; int v = e[j].v; if(v==0) continue; yiqi[v] = 1; } } int cnt = 0; for(int i=0;i<maxn;i++){ if(yiqi[i]==1){ cnt++; } } sort(anspoint.begin(),anspoint.end()); for(int i=0;i<anspoint.size();i++){ printf("%d%c",anspoint[i]," \n"[i==anspoint.size()-1]); } for(int i=0;i<maxn;i++){ if(yiqi[i]==1){ cnt--; printf("%d%c",i-m," \n"[cnt==0]); } } printf("%d\n",all-ans); return 0; }