最短路径的代价
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 - 携程编程大赛 (决赛)
解题思路:
这道题主要的思路是先求最短路,把所有的最短路在图中抠出来然后建一条以C为容量的容量网络。然后求
最小割。
点击打开链接 提交地址
const int inf = 1000000000 ;
const int maxn = 20000 , maxm = 500000 ;
struct Edge{
int v , f ,next ;
Edge(){}
Edge(int _v , int _f , int _next):v(_v) ,f(_f),next(_next){}
};
int sourse , meet ;
int id ;
Edge e[maxm*2 + 10] ;
int g[maxn + 10] ;
void add(int u , int v , int f){
e[++id] = Edge(v , f ,g[u]) ;
g[u] = id ;
e[++id] = Edge(u , 0 , g[v]) ;
g[v] = id ;
}
queue <int> que ;
bool vis[maxn + 10] ;
int dist[maxn + 10] ;
void bfs(){
memset(dist , 0 , sizeof(dist)) ;
while(! que.empty()) que.pop() ;
que.push(sourse) ;
vis[sourse] = 1 ;
while(! que.empty()){
int u = que.front() ; que.pop() ;
for(int i = g[u] ; i ; i = e[i].next){
int v = e[i].v ;
if(e[i].f && !vis[v]){
que.push(v) ;
dist[v] = dist[u] + 1 ;
vis[v] = 1 ;
}
}
}
}
int dfs(int u , int delta){
if(u == meet) return delta ;
int ans = 0 ;
for(int i = g[u] ; i && delta ; i = e[i].next){
int v = e[i].v ;
if(e[i].f && dist[v] == dist[u] + 1){
int d = dfs(v , min(delta , e[i].f)) ;
e[i].f -= d ;
e[i^1].f += d ;
delta -= d ;
ans += d ;
}
}
return ans ;
}
int maxflow(){
int ans = 0 ;
while(1){
memset(vis , 0 , sizeof(vis)) ;
bfs() ;
if(! vis[meet]) return ans ;
ans += dfs(sourse , inf) ;
}
}
void init(){
memset(g , 0 , sizeof(g)) ;
id = 1 ;
}
struct E{
int v , w , c ;
E(){}
E(int _v , int _w , int _c):v(_v) , w(_w) , c(_c){}
};
vector<E> lis[1008] ;
bool in[1008] ;
int mind[1008] ;
void spfa(int s){
memset(in , 0 , sizeof(in)) ;
memset(mind , 63 , sizeof(mind)) ;
queue<int> q ;
q.push(s) ;
in[s] = 1 ;
mind[s] = 0 ;
while(! q.empty()){
int u = q.front() ; q.pop() ;
in[u] = 0 ;
for(int i = 0 ; i < lis[u].size() ; i++){
int v = lis[u][i].v ;
int w = lis[u][i].w ;
if(mind[u] + w < mind[v]){
mind[v] = mind[u] + w ;
if(! in[v]){
q.push(v) ; in[v] = 1 ;
}
}
}
}
}
int main(){
int n , m , t , T = 1 , i , j ,u , v , w , c ;
while(cin>>n>>m){
if(n == 0 && m == 0) break ;
cin>>sourse>>meet ;
init() ;
for(i = 1 ; i <= n ; i++) lis[i].clear() ;
while(m--){
scanf("%d%d%d%d" ,&u ,&v , &w , &c) ;
lis[u].push_back(E(v , w , c)) ;
lis[v].push_back(E(u , w , c)) ;
}
spfa(sourse) ;
for(u = 1 ; u <= n ; u++){
for(i = 0 ; i < lis[u].size() ; i++){
v = lis[u][i].v ;
w = lis[u][i].w ;
c = lis[u][i].c ;
if(mind[u] + w == mind[v])
add(u , v , c) ;
}
}
printf("Case %d: %d\n" , T++ , maxflow()) ;
}
return 0 ;
}