zoukankan      html  css  js  c++  java
  • Marriage Match IV(最短路+网络流)

    Marriage Match IV

    http://acm.hdu.edu.cn/showproblem.php?pid=3416

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 6081    Accepted Submission(s): 1766


    Problem Description
    Do not sincere non-interference。
    Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once. 


    So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?
     
    Input
    The first line is an integer T indicating the case number.(1<=T<=65)
    For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.

    Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.

    At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
    There may be some blank line between each case.
     
    Output
    Output a line with a integer, means the chances starvae can get at most.
     
    Sample Input

    3
    7 8
    1 2 1
    1 3 1
    2 4 1
    3 4 1
    4 5 1
    4 6 1
    5 7 1
    6 7 1
    1 7

    6 7
    1 2 1
    2 3 1
    1 3 3
    3 4 1
    3 5 1
    4 6 1
    5 6 1
    1 6

    2 2
    1 2 1
    1 2 2
    1 2

     
    Sample Output
    2
    1
    1
      1 #include<iostream>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<cstdio>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<vector>
      9 #include<set>
     10 #define maxn 100005
     11 #define MAXN 10005
     12 #define mem(a,b) memset(a,b,sizeof(a))
     13 const int N=200005;
     14 const int M=200005;
     15 const int INF=0x3f3f3f3f;
     16 using namespace std;
     17 inline int read()
     18 {
     19     char ch=' ';
     20     int ans=0;
     21     while(ch<'0' || ch>'9')
     22         ch=getchar();
     23     while(ch<='9' && ch>='0')
     24     {
     25         ans=ans*10+ch-'0';
     26         ch=getchar();
     27     }
     28     return ans;
     29 }
     30 int n;
     31 vector<pair<int,int> >ve[maxn];
     32 int dis[maxn],dis1[maxn],dis2[maxn],vis[maxn];
     33 int a[maxn],b[maxn],c[maxn];
     34 struct sair{
     35     int pos,len;
     36     friend bool operator<(sair a,sair b){
     37         return a.len>b.len;
     38     }
     39 };
     40 
     41 
     42 void Dijstra(int s){
     43     for(int i=0;i<=n;i++){
     44         dis[i]=INF;
     45         vis[i]=0;
     46     }
     47     priority_queue<sair>Q;
     48     sair tmp;
     49     tmp.pos=s,tmp.len=0;
     50     Q.push(tmp);
     51     dis[s]=0;
     52     int now,Ne,len;
     53     while(!Q.empty()){
     54         tmp=Q.top();
     55         Q.pop();
     56         now=tmp.pos;
     57         if(!vis[now]){
     58             vis[now]=1;
     59             for(int i=0;i<ve[now].size();i++){
     60                 Ne=ve[now][i].first;
     61                 len=ve[now][i].second;
     62                 if(dis[Ne]>dis[now]+len){
     63                     dis[Ne]=dis[now]+len;
     64                     tmp.pos=Ne;
     65                     tmp.len=dis[Ne];
     66                     Q.push(tmp);
     67                 }
     68             }
     69         }
     70     }
     71 }
     72 
     73 
     74 struct Edge{
     75     int v,next;
     76     int cap,flow;
     77 }edge[MAXN*20];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
     78 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
     79 int cnt=0;//实际存储总边数
     80 void isap_init()
     81 {
     82     cnt=0;
     83     memset(pre,-1,sizeof(pre));
     84 }
     85 void isap_add(int u,int v,int w)//加边
     86 {
     87     edge[cnt].v=v;
     88     edge[cnt].cap=w;
     89     edge[cnt].flow=0;
     90     edge[cnt].next=pre[u];
     91     pre[u]=cnt++;
     92 }
     93 void add(int u,int v,int w){
     94     isap_add(u,v,1);
     95     isap_add(v,u,0);
     96 }
     97 bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
     98 {
     99     memset(dep,-1,sizeof(dep));
    100     memset(gap,0,sizeof(gap));
    101     gap[0]=1;
    102     dep[t]=0;
    103     queue<int>q;
    104     while(!q.empty())
    105     q.pop();
    106     q.push(t);//从汇点开始反向建层次图
    107     while(!q.empty())
    108     {
    109         int u=q.front();
    110         q.pop();
    111         for(int i=pre[u];i!=-1;i=edge[i].next)
    112         {
    113             int v=edge[i].v;
    114             if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
    115             {
    116                 dep[v]=dep[u]+1;
    117                 gap[dep[v]]++;
    118                 q.push(v);
    119                 //if(v==sp)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
    120                 //break;
    121             }
    122         }
    123     }
    124     return dep[s]!=-1;
    125 }
    126 int isap(int s,int t)
    127 {
    128     if(!bfs(s,t))
    129     return 0;
    130     memcpy(cur,pre,sizeof(pre));
    131     //for(int i=1;i<=n;i++)
    132     //cout<<"cur "<<cur[i]<<endl;
    133     int u=s;
    134     path[u]=-1;
    135     int ans=0;
    136     while(dep[s]<n)//迭代寻找增广路
    137     {
    138         if(u==t)
    139         {
    140             int f=INF;
    141             for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路
    142                 f=min(f,edge[i].cap-edge[i].flow);
    143             for(int i=path[u];i!=-1;i=path[edge[i^1].v])
    144             {
    145                 edge[i].flow+=f;
    146                 edge[i^1].flow-=f;
    147             }
    148             ans+=f;
    149             u=s;
    150             continue;
    151         }
    152         bool flag=false;
    153         int v;
    154         for(int i=cur[u];i!=-1;i=edge[i].next)
    155         {
    156             v=edge[i].v;
    157             if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow)
    158             {
    159                 cur[u]=path[v]=i;//当前弧优化
    160                 flag=true;
    161                 break;
    162             }
    163         }
    164         if(flag)
    165         {
    166             u=v;
    167             continue;
    168         }
    169         int x=n;
    170         if(!(--gap[dep[u]]))return ans;//gap优化
    171         for(int i=pre[u];i!=-1;i=edge[i].next)
    172         {
    173             if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
    174             {
    175                 x=dep[edge[i].v];
    176                 cur[u]=i;//常数优化
    177             }
    178         }
    179         dep[u]=x+1;
    180         gap[dep[u]]++;
    181         if(u!=s)//当前点没有增广路则后退一个点
    182         u=edge[path[u]^1].v;
    183      }
    184      return ans;
    185 }
    186 
    187 int main(){
    188     int T;
    189     T=read();
    190     while(T--){
    191         int m;
    192         n=read();
    193         m=read();
    194         for(int i=1;i<=n;i++){
    195             ve[i].clear();
    196         }
    197         for(int i=1;i<=m;i++){
    198             a[i]=read();
    199             b[i]=read();
    200             c[i]=read();
    201         }
    202         int s,t;
    203         s=read();
    204         t=read();
    205         for(int i=1;i<=m;i++){
    206              if(a[i]!=b[i])
    207             ve[a[i]].push_back(make_pair(b[i],c[i]));
    208         }
    209         Dijstra(s);
    210         memcpy(dis1,dis,sizeof(dis));
    211         for(int i=1;i<=n;i++){
    212             ve[i].clear();
    213         }
    214         for(int i=1;i<=m;i++){
    215             if(a[i]!=b[i])
    216             ve[b[i]].push_back(make_pair(a[i],c[i]));
    217         }
    218         Dijstra(t);
    219         memcpy(dis2,dis,sizeof(dis));
    220         isap_init();
    221         for(int i=1;i<=m;i++){
    222             if(a[i]!=b[i]&&dis1[a[i]]+dis2[b[i]]+c[i]==dis1[t]){
    223                 add(a[i],b[i],1);
    224             }
    225         }
    226         int ans=0;
    227         ans=isap(s,t);
    228         printf("%d
    ",ans);
    229     }
    230 }
    View Code
  • 相关阅读:
    git 常用命令
    spring源码-事件&监听3.6
    spring源码-国际化-3.5
    spring源码-Aware-3.4
    spring源码-BeanPostProcessor-3.3
    springboot中对yaml文件的解析
    数组Array.sort()排序的方法
    【转】js 对象按照键值(不分区大小写)排序,生成签名方法
    【转】JS常用函数整合库 lutils
    VS2017调试出现异常浏览器直接关闭的解决办法
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/9936728.html
Copyright © 2011-2022 走看看