题意:2个人从1走到n,假设一条路第一次走则是价值di,假设第二次还走这条路则须要价值di+ai,要你输出2个人到达终点的最小价值!
太水了!一条边建2次就OK了。第一次价值为di,第二次为ai+di,加入源点汇点跑最小费用最大流就OK了!
AC代码:
#include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 0x3f3f3f3f #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) int sumFlow; const int MAXN = 600+10; const int MAXM = 4000+10; struct Edge { int u, v, cap, cost; int next; }edge[MAXM<<2]; int NE; int head[MAXN], dist[MAXN], pp[MAXN]; bool vis[MAXN]; void init() { NE = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int cap, int cost) { edge[NE].u = u; edge[NE].v = v; edge[NE].cap = cap; edge[NE].cost = cost; edge[NE].next = head[u]; head[u] = NE++; edge[NE].u = v; edge[NE].v = u; edge[NE].cap = 0; edge[NE].cost = -cost; edge[NE].next = head[v]; head[v] = NE++; } bool SPFA(int s, int t, int n) { int i, u, v; queue <int> qu; memset(vis,false,sizeof(vis)); memset(pp,-1,sizeof(pp)); for(i = 0; i <= n; i++) dist[i] = INF; vis[s] = true; dist[s] = 0; qu.push(s); while(!qu.empty()) { u = qu.front(); qu.pop(); vis[u] = false; for(i = head[u]; i != -1; i = edge[i].next) { v = edge[i].v; if(edge[i].cap && dist[v] > dist[u] + edge[i].cost) { dist[v] = dist[u] + edge[i].cost; pp[v] = i; if(!vis[v]) { qu.push(v); vis[v] = true; } } } } if(dist[t] == INF) return false; return true; } int MCMF(int s, int t, int n) { int flow = 0; int i, minflow, mincost; mincost = 0; while(SPFA(s, t, n)) { minflow = INF + 1; for(i = pp[t]; i != -1; i = pp[edge[i].u]) if(edge[i].cap < minflow) minflow = edge[i].cap; flow += minflow; for(i = pp[t]; i != -1; i = pp[edge[i].u]) { edge[i].cap -= minflow; edge[i^1].cap += minflow; } mincost += dist[t] * minflow; } sumFlow = flow; return mincost; } int main() { int n,m; int cas=1; while(~scanf("%d%d",&n,&m)) { init(); int s=0; int t=n+1; for(int i=0;i<m;i++) { int u,v,w1,w2; scanf("%d %d %d %d",&u,&v,&w1,&w2); addedge(u,v,1,w1); addedge(u,v,1,w1+w2); } addedge(s,s+1,2,0); addedge(t-1,t,2,0); int ans=MCMF(s,t,t); printf("Case %d: %d ",cas++,ans); } return 0; }