ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[最短路,最大流最小割定理] 2019 Multi-University Training Contest 1 Path

2019-08-25 16:53:34  阅读:274  来源: 互联网

标签:dis1 Multi amn int Contest Training vis que dis


题目:http://acm.hdu.edu.cn/showproblem.php?pid=6582

Path

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3747    Accepted Submission(s): 1075


Problem Description Years later, Jerry fell in love with a girl, and he often walks for a long time to pay visits to her. But, because he spends too much time with his girlfriend, Tom feels neglected and wants to prevent him from visiting her.
After doing some research on the neighbourhood, Tom found that the neighbourhood consists of exactly n houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed 1 and go along the shortest path to hers, indexed n. 
Now Tom wants to block some of the roads so that Jerry has to walk longer to reach his girl's home, and he found that the cost of blocking a road equals to its length. Now he wants to know the minimum total cost to make Jerry walk longer.
Note, if Jerry can't reach his girl's house in the very beginning, the answer is obviously zero. And you don't need to guarantee that there still exists a way from Jerry's house to his girl's after blocking some edges.  

 

Input The input begins with a line containing one integer T(1≤T≤10), the number of test cases.
Each test case starts with a line containing two numbers n,m(1≤n,m≤10000), the number of houses and the number of one-way roads in the neighbourhood.
m lines follow, each of which consists of three integers x,y,c(1≤x,y≤n,1≤c≤109), denoting that there exists a one-way road from the house indexed x to y of length c.  

 

Output Print T lines, each line containing a integer, the answer.  

 

Sample Input 1 3 4 1 2 1 2 3 1 1 3 2 1 3 3  

 

Sample Output 3  

 

Source 2019 Multi-University Training Contest 1  

 

Recommend We have carefully selected several similar problems for you:  6718 6717 6716 6715 6714 

题意:

给n个节点m条有向边,现在可以删去一些边,代价为边权,问最小代价删去一些边使得现在节点1到节点n的最短路不成立(如果1不可达n则答案为0)

思路:

可能有多条1到n的最短路,这些最短路组成图,以最小代价使图不连通就是求最小割,由最大流最小割定理可知,最小割等于最大流,所以我们先找出图中1到n的最短路新建一个图,在这个图上从1到n跑一边最大流就可求出答案
现在就是建图的问题,我们先得到1到n的最短路径dis[i],再得到n到1的最短路径dis1[i],再把原图中符合dis[u]+e[i].w+dis1[v]==dis[n](令e[i].w为节点u到v的边权)的边建一个新图,
在这个新图上从1到n跑一边dinic就可得到答案

注意:

调了一个下午,在bool operator(const node &a)const{return a.w<w;}中原来是要a.w<w才能让优先队列中w小的优先,如果是a.w>w则是w大的优先

  1 #include<bits/stdc++.h>
  2 typedef long long ll;
  3 using namespace std;
  4 const int amn=1e4+5;
  5 const ll inf=1e18;
  6 struct edge{
  7     int from,to,nex;ll w;
  8 }eg[amn],eg1[amn],e[amn<<2|1];
  9 struct node{
 10     int p;
 11     ll w;
 12     node(int pp,ll ww){p=pp;w=ww;}
 13     bool operator<(const node &a)const{return a.w<w;}   ///调了一个下午,原来是要a.w<w才行,这样优先队列中才会w小的优先,如果是a.w>w则是w大的优先
 14 };
 15 ll head[amn],egn,head1[amn],egn1,n,m,dis[amn],dis1[amn],vis[amn],head2[amn],egn2;
 16 void init(int n){
 17     egn=0,egn1=0,egn2=1;    ///egn2是跑最大流的,初始为1,这样就可以从2开始加边,这样正向边和反向边相邻储存,因为2^1=3,3^1=2...所以可以异或得到正向边反向边
 18     for(int i=1;i<=n;i++)head2[i]=head1[i]=head[i]=0;
 19 }
 20 void add(int u,int v,ll w){     ///正向图加边
 21     eg[++egn].nex=head[u];
 22     head[u]=egn;
 23     eg[egn].from=u;
 24     eg[egn].to=v;
 25     eg[egn].w=w;
 26 }
 27 void add1(int u,int v,ll w){    ///反向图加边
 28         eg1[++egn1].nex=head1[u];
 29         head1[u]=egn1;
 30         eg1[egn1].from=u;
 31         eg1[egn1].to=v;
 32         eg1[egn1].w=w;
 33     }
 34 void add2(int u,int v,ll w){    ///跑最大流的新图加边
 35         e[++egn2].nex=head2[u];
 36         head2[u]=egn2;
 37         e[egn2].from=u;
 38         e[egn2].to=v;
 39         e[egn2].w=w;
 40     }
 41 
 42 ///以1为起点跑最短路
 43 void dijkstra(int s){
 44     memset(vis,0,sizeof vis);
 45     for(int i=0;i<=n;i++)dis[i]=inf;
 46     dis[s]=0;
 47     priority_queue<node> q;
 48     q.push(node(s,dis[s]));
 49     while(q.size()){
 50         int u=q.top().p;
 51         ll w=q.top().w;q.pop();
 52         if(w>dis[u])continue;
 53         vis[u]=1;
 54         for(int i=head[u];i;i=eg[i].nex){
 55             int v=eg[i].to;
 56             if(!vis[v]&&((dis[v])>(eg[i].w)+(dis[u]))){
 57                 dis[v]=(eg[i].w)+dis[u];
 58                 q.push(node(v,(dis[v])));
 59             }
 60         }
 61     }
 62 }
 63 ///以n为起点跑最短路
 64 void dijkstra1(int s){
 65     memset(vis,0,sizeof vis);
 66     for(int i=0;i<=n;i++)dis1[i]=inf;
 67     dis1[s]=0;
 68     priority_queue<node> q;
 69     q.push(node(s,dis1[s]));
 70     while(q.size()){
 71         int u=q.top().p;
 72         ll w=q.top().w;q.pop();
 73         if(w>dis1[u])continue;
 74         vis[u]=1;
 75         for(int i=head1[u];i;i=eg1[i].nex){
 76             int v=eg1[i].to;
 77             if(!vis[v]&&((dis1[v])>(eg1[i].w)+(dis1[u]))){
 78                 dis1[v]=(eg1[i].w)+dis1[u];
 79                 q.push(node(v,(dis1[v])));
 80             }
 81         }
 82     }
 83 }
 84 ///dinic最大流
 85 queue<int> que;
 86 ll dist[amn],src=1,sink=n;
 87 void bfs(){
 88     memset(dist,0,sizeof dist);
 89     while(que.size())que.pop();
 90     vis[src]=1;
 91     que.push(src);
 92     while(que.size()){
 93         int u=que.front();que.pop();
 94         for(int i=head2[u];i;i=e[i].nex){
 95             int v=e[i].to;//cout<<'>'<<e[i].w<<' '<<v<<endl;
 96             if(e[i].w&&!vis[v]){
 97                 que.push(v);
 98                 dist[v]=dist[u]+1;
 99                 vis[v]=1;
100             }
101         }
102     }
103 }
104 int dfs(int u,ll delta){
105     if(u==sink)return delta;
106     int ret=0;
107     for(int i=head2[u];delta&&i;i=e[i].nex)
108     if(e[i].w&&(dist[e[i].to]==dist[u]+1)){
109         ll dd=dfs(e[i].to,min(e[i].w,delta));
110         e[i].w-=dd;
111         e[i^1].w+=dd;
112         delta-=dd;
113         ret+=dd;
114     }
115     return ret;
116 }
117 ll maxflow(){
118     ll ret=0;
119     while(1){
120         memset(vis,0,sizeof vis);
121         bfs();
122         if(!vis[sink])return ret;//cout<<'<'<<ret<<endl;
123         ret+=dfs(src,inf);
124     }
125 }
126 int main(){
127     int T,x,y;ll c;
128     scanf("%d",&T);
129     while(T--){
130         scanf("%lld%lld",&n,&m);
131         init(n);            ///初始化
132         src=1,sink=n;       ///设置1为源点,n为汇点
133         for(int i=1;i<=m;i++){
134             scanf("%d%d%lld",&x,&y,&c);
135             add(x,y,c);     ///正向图,为了以1为起点跑最短路
136             add1(y,x,c);    ///反向图,为了以n为起点跑最短路
137         }
138         dijkstra(1);        ///以1为起点的最短路
139         if(dis[n]==inf){printf("0\n");continue;}    ///如果1到n不可达则输出0
140         dijkstra1(n);       ///以n为起点的最短路
141         for(int i=1;i<=egn;i++){
142 //            cout<<eg[i].from<<' '<<eg[i].to<<' '<<eg[i].w<<endl;
143 //            cout<<dis[eg[i].from]<<' '<<eg[i].w<<' '<<dis1[eg[i].to]<<' '<<dis[n]<<endl<<endl;
144             if(dis[eg[i].from]+eg[i].w+dis1[eg[i].to]==dis[n]){     ///如果1到现在这个点u的最短路径+u到v的边权+v到n的最短路径==1到n的最短路径则u到v这条边是最短路中的一条边
145                 add2(eg[i].from,eg[i].to,eg[i].w);  ///建新图,加正向边
146                 add2(eg[i].to,eg[i].from,0);        ///边权为0的反向边
147             }
148         }
149         printf("%lld\n",maxflow());     ///最大流等于最小割
150     }
151 }
152 /**
153 给n个节点m条有向边,现在可以删去一些边,代价为边权,问最小代价删去一些边使得现在节点1到节点n的最短路不成立(如果1不可达n则答案为0)
154 可能有多条1到n的最短路,这些最短路组成图,以最小代价使图不连通就是求最小割,由最大流最小割定理可知,最小割等于最大流,所以我们先找出图中1到n的最短路新建一个图,在这个图上从1到n跑一边最大流就可求出答案
155 现在就是建图的问题,我们先得到1到n的最短路径dis[i],再得到n到1的最短路径dis1[i],再把原图中符合dis[u]+e[i].w+dis1[v]==dis[n](令e[i].w为节点u到v的边权)的边建一个新图,
156 在这个新图上从1到n跑一边dinic就可得到答案
157 调了一个下午,在bool operator(const node &a)const{return a.w<w;}中原来是要a.w<w才能让优先队列中w小的优先,如果是a.w>w则是w大的优先
158 **/

 

标签:dis1,Multi,amn,int,Contest,Training,vis,que,dis
来源: https://www.cnblogs.com/Railgun000/p/11408406.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有