【题目链接】 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2230
【题目大意】
给出一张图,从1到n的最长路不变的情况下,
还能在不同的点之间增加最长总和的路为多长。
【题解】
From http://www.hankcs.com/program/algorithm/aoj-2230-how-to-create-a-good-game.html
如果将原DAG权值取反,然后从最后一关连一条正权边到第一关,
权值是最短路(负权值最短路=传统意义上的最长路)的长度的话,
那么那些正圈中的负权边就是应该增加权值的边,具体应该加多少,就是正圈的权值。
新建源点汇点,对于所有顶点,如果入度>出度,从源点连一条边到它,
否则,从它连一条边到汇点,容量都是是度数差。
【代码】
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; const int INF=0x3f3f3f3f; struct edge{ int to,cap,cost,rev; edge(int to,int cap,int cost,int rev):to(to),cap(cap),cost(cost),rev(rev){} }; const int MAX_V=10010; int V,dist[MAX_V],prevv[MAX_V],preve[MAX_V]; vector<edge> G[MAX_V]; void add_edge(int from,int to,int cap,int cost){ G[from].push_back(edge(to,cap,cost,G[to].size())); G[to].push_back(edge(from,0,-cost,G[from].size()-1)); } int min_cost_flow(int s,int t,int f){ int res=0; while(f>0){ fill(dist,dist+V,INF); dist[s]=0; bool update=1; while(update){ update=0; for(int v=0;v<V;v++){ if(dist[v]==INF)continue; for(int i=0;i<G[v].size();i++){ edge &e=G[v][i]; if(e.cap>0&&dist[e.to]>dist[v]+e.cost){ dist[e.to]=dist[v]+e.cost; prevv[e.to]=v; preve[e.to]=i; update=1; } } } } if(dist[t]==INF)return -1; int d=f; for(int v=t;v!=s;v=prevv[v]){ d=min(d,G[prevv[v]][preve[v]].cap); }f-=d; res+=d*dist[t]; for(int v=t;v!=s;v=prevv[v]){ edge &e=G[prevv[v]][preve[v]]; e.cap-=d; G[v][e.rev].cap+=d; } }return res; } void clear(){for(int i=0;i<V;i++)G[i].clear();} const int MAX_N=120; int N,M; int in[MAX_N],out[MAX_N],tot; void solve(){ int s=N,t=N+1;V=t+1;tot=0; clear(); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); for(int i=0;i<M;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); add_edge(x,y,INF,-z); out[x]++;in[y]++; tot+=z; }int max_f=0; for(int i=0;i<N;i++){ if(in[i]>out[i]){ add_edge(s,i,in[i]-out[i],0); max_f+=in[i]-out[i]; }else{ add_edge(i,t,out[i]-in[i],0); } }min_cost_flow(0,N-1,1); add_edge(N-1,0,INF,-dist[N-1]); printf("%d\n",min_cost_flow(s,t,max_f)-tot); } int main(){ while(~scanf("%d%d",&N,&M)){ solve(); }return 0; }
时间: 2024-11-02 16:31:47