zoukankan      html  css  js  c++  java
  • hdu3416 最短路+最大流

    题意:有 n 点 m 边,有出发点 A 到达点 B ,只允许走原图中的最短路,但每条边只允许被走一次,问最多能找出多少条边不重复的最短路

    一开始做到的时候瞎做了一发最短路,WA了之后也知道显然不对,就放着了,后来打了今年的多校,再做到的时候发现和多校第一场的1007一样的……最短路+网络流就行了,只不过第一次做这个的时候我还不知道网络流是啥,不会做也正常啦。

    首先对于原图跑一遍最短路求出每个点距离 A 点的最短路,然后对于每一条边,如果它的权值等于它连接的两点的最短路的差值的时候,就说明这条路是最短路上的边,将这个边加入网络流的建图中,流量定为1表示这条边只能用一次,这样跑一遍最大流就能直接解决问题了。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<algorithm>
      4 #include<queue>
      5 #include<vector>
      6 using namespace std;
      7 typedef pair<int,int> pii;
      8 const int maxm=1005;
      9 const int INF=0x3f3f3f3f;
     10 
     11 struct cmp{
     12     bool operator()(pii a,pii b){
     13         return a.first>b.first;
     14     }
     15 };
     16 
     17 int head[1005],point[100005],val[100005],nxt[100005],size;
     18 bool vis[100005];
     19 int dis[1005],n,s,p,fa[1005],pa[1005];
     20 
     21 
     22 struct edge{             //弧的结构体,变量:弧的出发点、结束点、容量、流量
     23     int from,to,c,f;
     24     edge(int a,int b,int m,int n):from(a),to(b),c(m),f(n){}
     25 };
     26 
     27 struct dinic{
     28     int m,s,t;                    //边数、源点标号、汇点标号
     29     vector<edge>e;        //
     30     vector<int>g[maxm];    //g[i][j]表示第i个点出发的第j条边在e中的编号
     31     bool vis[maxm];
     32     int d[maxm],cur[maxm];    //d为源点到点的距离,cur为当前遍历到的边
     33     void init(int n){                //初始化,n为点数量(标号0~n-1)
     34         for(int i=0;i<n+5;i++)g[i].clear();
     35         e.clear();
     36     }
     37     void add(int a,int b,int v){        //加入弧和反向弧
     38         e.push_back(edge(a,b,v,0));    //正向弧容量v,反向弧容量0
     39         e.push_back(edge(b,a,0,0));
     40         m=e.size();
     41         g[a].push_back(m-2);
     42         g[b].push_back(m-1);
     43     }
     44     bool bfs(){
     45         memset(vis,0,sizeof(vis));
     46         queue<int>q;
     47         q.push(s);
     48         d[s]=0;
     49         vis[s]=1;
     50         while(!q.empty()){
     51             int u=q.front();q.pop();
     52             for(int i=0;i<g[u].size();i++){
     53                 edge tmp=e[g[u][i]];
     54                 if(!vis[tmp.to]&&tmp.c>tmp.f){
     55                     vis[tmp.to]=1;
     56                     d[tmp.to]=d[u]+1;
     57                     q.push(tmp.to);
     58                 }
     59             }
     60         }
     61         return vis[t];
     62     }
     63     int dfs(int x,int a){
     64         if(x==t||a==0)return a;
     65         int flow=0,f;
     66         for(int& i=cur[x];i<g[x].size();i++){
     67             edge &tmp=e[g[x][i]];
     68             if(d[x]+1==d[tmp.to]&&(f=dfs(tmp.to,min(a,tmp.c-tmp.f)))>0){
     69                 tmp.f+=f;
     70                 e[g[x][i]^1].f-=f;
     71                 flow+=f;
     72                 a-=f;
     73                 if(a==0)break;
     74             }
     75         }
     76         if(!flow)d[x]=-1;
     77         return flow;
     78     }
     79     int mf(int s,int t){                //在主函数中使用的函数,求s到t的最大流
     80         this->s=s;
     81         this->t=t;
     82         int flow=0;
     83         while(bfs()){
     84             memset(cur,0,sizeof(cur));
     85             flow+=dfs(s,INF);
     86         }
     87         return flow;
     88     }
     89 };
     90 
     91 void add(int a,int b,int v){
     92     point[size]=b;
     93     val[size]=v;
     94     nxt[size]=head[a];
     95     head[a]=size++;
     96 }
     97 
     98 void dij(){
     99     int i;
    100     priority_queue<pii,vector<pii>,cmp>q;
    101     memset(dis,0x3f,sizeof(dis));
    102     memset(fa,-1,sizeof(fa));
    103     dis[s]=0;
    104     q.push(make_pair(dis[s],s));
    105     while(!q.empty()){
    106         pii u=q.top();
    107         q.pop();
    108         if(u.first>dis[u.second])continue;
    109         for(i=head[u.second];~i;i=nxt[i]){
    110             int j=point[i],v=u.first+val[i];
    111             if(!vis[i]&&dis[j]>v){
    112                 dis[j]=v;
    113                 fa[j]=u.second;
    114                 pa[j]=i;
    115                 q.push(make_pair(dis[j],j));
    116             }
    117         }
    118     }
    119 }
    120 
    121 int main(){
    122     int t;
    123     scanf("%d",&t);
    124     for(int q=1;q<=t;q++){
    125         int m,i;
    126         memset(head,-1,sizeof(head));
    127         memset(vis,0,sizeof(vis));
    128         size=0;
    129         scanf("%d%d",&n,&m);
    130         for(i=1;i<=m;i++){
    131             int a,b,v;
    132             scanf("%d%d%d",&a,&b,&v);
    133             if(a!=b){
    134                 add(a,b,v);
    135             }
    136         }
    137         scanf("%d%d",&s,&p);
    138         dinic d;
    139         dij();
    140         for(i=1;i<=n;++i){
    141             for(int j=head[i];~j;j=nxt[j]){
    142                 int k=point[j];
    143                 if(dis[i]+val[j]==dis[k])d.add(i,k,1);
    144             }
    145         }
    146         printf("%d
    ",d.mf(s,p));
    147     }
    148     return 0;
    149 }
    View Code
  • 相关阅读:
    Elasticsearch 支持拼音自动补全
    laravel自动补全链接
    laravel的服务容器(药箱)、服务提供者(小盒子)、Facades(更方便用药),方便大家透彻理解
    php static静态属性和静态方法
    php面向对象的构造方法与析构方法
    MySQL事务-ROLLBACK,COMMIT用法详解
    php 事务处理transaction
    Python:初步学习Python
    iOS:自己写的一个星级评价的小Demo
    iOS:枚举enum的使用
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4787530.html
Copyright © 2011-2022 走看看