标签:
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2925 Accepted Submission(s): 1407
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int INF = 999999999; const int N = 405; const int M = 200005; struct Edge{ int u,v,cap,cost,next; }edge[M]; int head[N],tot,low[N],pre[N]; int total ; bool vis[N]; int flag[N][N]; void addEdge(int u,int v,int cap,int cost,int &k){ edge[k].u=u,edge[k].v=v,edge[k].cap = cap,edge[k].cost = cost,edge[k].next = head[u],head[u] = k++; edge[k].u=v,edge[k].v=u,edge[k].cap = 0,edge[k].cost = -cost,edge[k].next = head[v],head[v] = k++; } void init(){ memset(head,-1,sizeof(head)); tot = 0; } bool spfa(int s,int t,int n){ memset(vis,false,sizeof(vis)); for(int i=0;i<=n;i++){ low[i] = (i==s)?0:INF; pre[i] = -1; } queue<int> q; q.push(s); while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = false; for(int k=head[u];k!=-1;k=edge[k].next){ int v = edge[k].v; if(edge[k].cap>0&&low[v]>low[u]+edge[k].cost){ low[v] = low[u] + edge[k].cost; pre[v] = k; ///v为终点对应的边 if(!vis[v]){ vis[v] = true; q.push(v); } } } } if(pre[t]==-1) return false; return true; } int MCMF(int s,int t,int n){ int mincost = 0,minflow,flow=0; while(spfa(s,t,n)) { minflow=INF+1; for(int i=pre[t];i!=-1;i=pre[edge[i].u]) minflow=min(minflow,edge[i].cap); flow+=minflow; for(int i=pre[t];i!=-1;i=pre[edge[i].u]) { edge[i].cap-=minflow; edge[i^1].cap+=minflow; } mincost+=low[t]*minflow; } total=flow; return mincost; } int n,m; int main(){ int tcase; scanf("%d",&tcase); while(tcase--){ init(); scanf("%d%d",&n,&m); int src = 0,des = 2*n+1; for(int i=1;i<=n;i++){ addEdge(src,i,1,0,tot); addEdge(i+n,des,1,0,tot); } memset(flag,-1,sizeof(flag)); for(int i=1;i<=m;i++){ ///去重 int u,v,w; scanf("%d%d%d",&u,&v,&w); if(flag[u][v]==-1||w<flag[u][v]){ flag[u][v] = w; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(flag[i][j]!=-1){ addEdge(i,j+n,1,flag[i][j],tot); } } } int mincost = MCMF(src,des,2*n+2); if(total!=n) printf("-1\n"); else printf("%d\n",mincost); } }
题解二:KM算法,也是将一个点看成两个点,算最优匹配即可.
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int INF = 999999999; const int N = 405; int graph[N][N]; int lx[N],ly[N]; int linker[N]; bool x[N],y[N]; int n,m; void init(){ memset(lx,0,sizeof(lx)); memset(ly,0,sizeof(ly)); memset(linker,-1,sizeof(linker)); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(lx[i]<graph[i][j]) lx[i] = graph[i][j]; } } } bool dfs(int u){ x[u] = true; for(int i=1;i<=n;i++){ if(!y[i]&&graph[u][i]==lx[u]+ly[i]){ y[i] = true; if(linker[i]==-1||dfs(linker[i])){ linker[i] = u; return true; } } } return false; } int KM(){ int sum = 0; init(); for(int i=1;i<=n;i++){ while(1){ memset(x,false,sizeof(x)); memset(y,false,sizeof(y)); if(dfs(i)) break; int d = INF; for(int j=1;j<=n;j++){ if(x[j]){ for(int k=1;k<=n;k++){ if(!y[k]) d = min(d,lx[j]+ly[k]-graph[j][k]); } } } if(d==INF) break; for(int j=1;j<=n;j++){ if(x[j]) lx[j]-=d; if(y[j]) ly[j]+=d; } } } for(int i=1;i<=n;i++){ sum+=graph[linker[i]][i]; } return sum; } int main() { int tcase; scanf("%d",&tcase); while(tcase--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ graph[i][j] = -INF; } } for(int i=1;i<=m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); graph[u][v] = max(graph[u][v],-w); } int ans = KM(); printf("%d\n",-ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/liyinggang/p/5729535.html