最短路径的代价
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 32 Accepted Submission(s) : 15
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
通常情况下找到N个节点、M 条边的无向图中某两点的最短路径很简单。假设每条边都有各自的长度以及删除这条边的代价,那么给出两个点X和Y,删除一些边可以使得X到Y的最短路径增加,求删除边最少的代价。
Input
第一行包含参数N和M,分别表示节点和边的个数
(2 ≤N≤ 1000,1 ≤M≤ 11000 );
第二行包含参数X和Y,表示源点和终点( 1 ≤ X,Y ≤ N,X ≠ Y);
剩下M行每行包含4个参数Ui、Vi、Wi和Ci,分别表示节点Ui和Vi之间边的长度Wi以及删除的代价Ci ( 1 ≤ Ui , Vi ≤ N, 0 ≤Wi, Ci ≤1000 );
如果某行N=M=0就表示输入结束。
第二行包含参数X和Y,表示源点和终点( 1 ≤ X,Y ≤ N,X ≠ Y);
剩下M行每行包含4个参数Ui、Vi、Wi和Ci,分别表示节点Ui和Vi之间边的长度Wi以及删除的代价Ci ( 1 ≤ Ui , Vi ≤ N, 0 ≤Wi, Ci ≤1000 );
如果某行N=M=0就表示输入结束。
Output
对于每个用例,按行输出增加X和Y直接最短路径所需要的最小代价。这个代价是所有删除的边的代价之和。
Sample Input
2 3 1 2 1 2 2 3 1 2 2 4 1 2 3 5 4 5 1 4 1 2 1 1 2 3 1 1 3 4 1 1 1 4 3 2 2 2 2 3 4 5 2 3 1 2 3 2 2 4 3 4 1 3 2 3 3 4 2 3 1 4 0 1 0 0
Sample Output
7 3 6
Source
CodingTrip - 携程编程大赛 (决赛)
LINK: http://acm.ustc.edu.cn/ustcoj/problem.php?id=1280
这个比赛好多原题,无论是资格赛还是决赛,不吐槽了。 可惜我没有见过几道啊。
这道题目是说, 给你一个图,从s到t 有最短路,图上的每条边都有长度和 删去的代价。要求删除一些边,使得由s->t的最短路增大。要求删掉的边的代价最小。
解法: 先求s->t的最短路。建立新图,如果dis[u]==dis[v]+ 由v到u的边的长度,则添加边(v,u),边长为删去的代价.
之后就是求一个最小割/最大流,把s,t分开.
这个比赛好多原题,无论是资格赛还是决赛,不吐槽了。 可惜我没有见过几道啊。
这道题目是说, 给你一个图,从s到t 有最短路,图上的每条边都有长度和 删去的代价。要求删除一些边,使得由s->t的最短路增大。要求删掉的边的代价最小。
解法: 先求s->t的最短路。建立新图,如果dis[u]==dis[v]+ 由v到u的边的长度,则添加边(v,u),边长为删去的代价.
之后就是求一个最小割/最大流,把s,t分开.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define INF 1000000000
#define N 1005
#define M 100005
int n,m,s,t,hh1[N],hh2[N],tot1,tot2;
int dis[N],inq[N],vis[N],lev[N];
struct node
{
int u,v,w,c,next;
}edge1[2*M],edge2[2*M];
void init()
{
tot1=tot2=0;
memset(hh1,-1,sizeof(hh1));
memset(hh2,-1,sizeof(hh2));
}
void add1(int u,int v,int w,int c)
{
edge1[tot1].u=u; edge1[tot1].v=v;
edge1[tot1].w=w; edge1[tot1].c=c;
edge1[tot1].next=hh1[u]; hh1[u]=tot1++;
}
void add2(int u,int v,int c)
{
edge2[tot2].u=u; edge2[tot2].v=v;
edge2[tot2].w=c; edge2[tot2].next=hh2[u];
hh2[u]=tot2++;
edge2[tot2].u=v; edge2[tot2].v=u;
edge2[tot2].w=0; edge2[tot2].next=hh2[v];
hh2[v]=tot2++;
}
void spfa()
{
queue<int > Q;
Q.push(s);
memset(inq,0,sizeof(inq));
inq[s]=1;
for(int i=0;i<=n;i++) dis[i]=INF;
dis[s]=0;
while(!Q.empty())
{
int u=Q.front(); Q.pop();
inq[u]--;
for(int i=hh1[u];i!=-1;i=edge1[i].next)
{
int v=edge1[i].v;
if(dis[v]>dis[u]+edge1[i].w)
{
dis[v]=dis[u]+edge1[i].w;
if(!inq[v])
{
inq[v]=1;
Q.push(v);
}
}
}
}
}
void add_()
{
for(int u=1;u<=n;u++)
{
for(int j=hh1[u];j!=-1;j=edge1[j].next )
{
int v=edge1[j].v;
if(dis[v]==dis[u]+edge1[j].w) add2(u,v,edge1[j].c);
}
}
}
int bfs()
{
queue<int > Q;
memset(lev,-1,sizeof(lev));
lev[s]=1; Q.push(s);
while(!Q.empty())
{
int u=Q.front(); Q.pop();
for(int i=hh2[u];i!=-1; i=edge2[i].next )
{
int v=edge2[i].v;
if(edge2[i].w && lev[v]==-1)
{
lev[v]=lev[u]+1;
Q.push(v);
}
}
}
return lev[t]!=-1;
}
int dfs(int u,int flow)
{
if(u==t) return flow;
int tmp=flow;
for(int i=hh2[u];i!=-1; i=edge2[i].next )
{
int v=edge2[i].v;
if(lev[v]==lev[u]+1)
{
int ad=dfs(v,min(tmp,edge2[i].w));
tmp-=ad;
edge2[i].w-=ad;
edge2[i^1].w+=ad;
if(!tmp) break;
}
}
return flow-tmp;
}
int dinic()
{
int ret=0;
while(bfs())
{
ret+=dfs(s,INF);
}
return ret;
}
int main()
{
//freopen("in.txt","r",stdin);
int time=0;
while(scanf("%d%d",&n,&m),n||m)
{
scanf("%d%d",&s,&t);
init();
int u,v,w,c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&u,&v,&w,&c);
add1(u,v,w,c);
add1(v,u,w,c);
}
spfa();
memset(vis,0,sizeof(vis));
add_();
int ans=dinic();
printf("Case %d: %d\n",++time,ans);
//printf("%d\n",ans);
}
return 0;
}