1506: Double Shortest Paths
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 84 Solved: 22
[ Submit][ Status][ Web Board]
Description
Input
There will be at most 200 test cases. Each case begins with two integers n, m (1<=n<=500, 1<=m<=2000), the number of caves and passages. Each of the following m lines contains four integers u, v, di and ai (1<=u,v<=n, 1<=di<=1000, 0<=ai<=1000). Note that there can be multiple passages connecting the same pair of caves, and even passages connecting a cave and itself.
Output
For each test case, print the case number and the minimal total difficulty.
Sample Input
4 4
1 2 5 1
2 4 6 0
1 3 4 0
3 4 9 1
4 4
1 2 5 10
2 4 6 10
1 3 4 10
3 4 9 10
Sample Output
Case 1: 23
Case 2: 24
HINT
Source
两个人从起点走到终点 第一个人走的时候所花分费用为边上第一个值 第二个人走的时候所花的费用为第一个值加上第二个值求两个人走到终点所花的最小费用
对于u->v 建两条边 容量都为1 第一个的费用为第一个值 第二个的费用为两个值的和
另外再加上超级源点到起点的边 终点到超级汇点的边
最小费用流求出最小费用就可以了
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 100000
#define MAXM 100000
#define INF 0x3f3f3f3f
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
void read(int &x)
{
char ch;
x=0;
while(ch=getchar(),ch!=' '&&ch!='\n')
{
x=x*10+ch-'0';
}
}
struct Edge
{
int to,next,cap,flow,cost;
}edge[MAXM];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N;
void init(int n)
{
N=n;
tol=0;
MEM(head,-1);
}
void addedge(int u,int v,int cap,int cost)
{
edge[tol].to=v;
edge[tol].cap=cap;
edge[tol].cost=cost;
edge[tol].flow=0;
edge[tol].next=head[u];
head[u]=tol++;
edge[tol].to=u;
edge[tol].cap=0;
edge[tol].cost=-cost;
edge[tol].flow=0;
edge[tol].next=head[v];
head[v]=tol++;
}
bool spfa(int s,int t)
{
queue<int> q;
for(int i=0;i<N;i++)
{
dis[i]=INF;
vis[i]=false;
pre[i]=-1;
}
dis[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost)
{
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
if(pre[t]==-1) return false;
return true;
}
int minCostMaxflow(int s,int t,int &cost)
{
int flow=0;
cost=0;
while(spfa(s,t))
{
int Min=INF;
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to])
{
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
}
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
cost+=edge[i].cost*Min;
}
flow+=Min;
}
return flow;
}
int main()
{
// fread;
int n,m;
int cs=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
init(n+2);
for(int i=0;i<m;i++)
{
int u,v,c1,c2;
scanf("%d%d%d%d",&u,&v,&c1,&c2);
addedge(u,v,1,c1);
addedge(u,v,1,c1+c2);
}
int s=0,t=n+1;
addedge(0,1,2,0);
addedge(n,t,2,0);
int cost;
minCostMaxflow(s,t,cost);
printf("Case %d: %d\n",cs++,cost);
}
return 0;
}