ICode9

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

hdu3416——最短路+最大流

2019-07-30 10:02:37  阅读:252  来源: 互联网

标签:head 最大 hdu3416 int 短路 dep edge MAXN tol


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416

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

不要真诚不干涉。‎
‎喜欢那个节目,现在明星也参加一个节目,但它发生在城市A和B之间。Starvae在城市A和女孩在城市B。每次Starvae可以到达城市B,并与他喜欢的女孩做数据。但有两个问题,一个是星华必须在最短的时间内到达B,据说他必须走最短的路。其他是没有道路可以采取不止一次。而城市之星去世可以不止一次。‎
‎因此,在一个好的RP下,Starvae可能有很多机会到达城市B。 ‎
‎ ‎
‎但他不知道有多少机会,他最多能与他喜欢的女孩做数据。你能帮starva吗?‎

‎输入‎

‎第一行是表示案例编号的整数 T。(1<_T<#65)‎
‎对于每种情况下,第一行中有两个整数 n 和 m(2<\n_lt;#1000,0_lt;_m_lt;#100000)是城市数,m 是道路数。‎
‎然后跟随 m 行,每行有三个整数 a、b、c、(1_lt;_a,b_lt;n,0_lt;c_lt;_lt;_lt;_1000)表示有一条从 a 到 b 的路,其距离为 c,而从 b 到 a 可能没有‎
‎道路。可能有一条路从一条路到一条路,但你可以忽略它。如果从 a 到 b 有两条道路,则它们是不同的。最后是一条包含两个整数 A 和 B(1_lt;#A,B_lt;_N,A!=B)的行,表示城市 A‎
‎和城市 B 的数量。每个案例之间可能存在一些空白行。 ‎
‎ ‎

‎输出‎

‎输出一个整数的线,意味着星形最多只能得到的机会。

 

题意其实就是让你求有几个最短路径。

首先我们需要清楚一个定理,如果一个边是最短路上的边,那么一定满足dis[e.from]+e.dis=dis[e.to];

之后就很好写了,也很经典了,

首先跑一个最短路,求出满足dis[e.from]+e.dis=dis[e.to]的边,即最短路上的边。

然后对每条最短路上的边建最大流边,容量为1,求出最大流即为结果。

不过最短路要用基于最小堆的DIjkstra算法实现,SPFA会超时。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1e5+7;
const int maxm=1e5+7;
struct Edge{
    int from,to;
    LL val;
};
struct HeapNode{
    LL d;           
    int u;
    bool operator < (const HeapNode & rhs) const{
		return d > rhs.d;
	}  
};
struct Dijstra{
    int n,m;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool used[maxn];
    LL d[maxn];
    int p[maxn];

    void init(int n){
        this->n = n;
        for(int i=0;i<=n;++i)    G[i].clear();
        edges.clear();
        memset(used,0,sizeof(used));
    }

    void Addedge(int from,int to ,LL dist){
        edges.push_back((Edge){from,to,dist});
        m = edges.size();
        G[from].push_back(m-1);
    }

    void dijkstra(int s){   
        priority_queue<HeapNode> Q;
        for(int i=0;i<=n;++i)    d[i]=INF;
        d[s]=0;
        Q.push((HeapNode){0,s});
        while(!Q.empty()){
            HeapNode x =Q.top();Q.pop();
            int u =x.u;
            if(used[u]) 
                continue;
            used[u]= true;
            for(int i=0;i<G[u].size();++i){
                Edge & e = edges[G[u][i]];
                if(d[e.to] > d[u] + e.val){
                    d[e.to] = d[u] +e.val;
                    p[e.to] = G[u][i];
                    Q.push((HeapNode){d[e.to],e.to});
                }
            }
        }
    }
}Dijk;
const int MAXN=1010;
const int MAXM=200010;
struct Node{
    int from,to,next;
    int cap;
};
struct SAP_MaxFlow{
    int n,m;        
    int tol;
    int head[MAXN];
    int dep[MAXN];
    int gap[MAXN];
    Node edge[MAXM];

    void init(int N){
        this->n = N;
        this->tol=0;
        memset(head,-1,sizeof(head));
    }

    void AddEdge(int u,int v,int w){
        edge[tol].from=u;edge[tol].to=v;edge[tol].cap=w;edge[tol].next=head[u];head[u]=tol++;
        edge[tol].from=v;edge[tol].to=u;edge[tol].cap=0;edge[tol].next=head[v];head[v]=tol++;
    }

    void BFS(int start,int end)
    {
        memset(dep,-1,sizeof(dep));
        memset(gap,0,sizeof(gap));
        gap[0]=1;
        int que[MAXN];
        int front,rear;
        front=rear=0;
        dep[end]=0;
        que[rear++]=end;
        while(front!=rear){
            int u=que[front++];
            if(front==MAXN)front=0;
            for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                if(dep[v]!=-1)continue;
                que[rear++]=v;
                if(rear==MAXN)rear=0;
                dep[v]=dep[u]+1;
                ++gap[dep[v]];
            }
        }
    }
    int SAP(int start,int end)
    {
        int res=0;
        BFS(start,end);
        int cur[MAXN];
        int S[MAXN];
        int top=0;
        memcpy(cur,head,sizeof(head));
        int u=start;
        int i;
        while(dep[start]<n){
            if(u==end){
                int temp=INF;
                int inser;
                for(i=0;i<top;i++)
                   if(temp>edge[S[i]].cap){
                       temp=edge[S[i]].cap;
                       inser=i;
                   }
                for(i=0;i<top;i++){
                    edge[S[i]].cap-=temp;
                    edge[S[i]^1].cap+=temp;
                }
                res+=temp;
                top=inser;
                u=edge[S[top]].from;
            }
            if(u!=end&&gap[dep[u]-1]==0)//出现断层,无增广路
              break;
            for(i=cur[u];i!=-1;i=edge[i].next)
               if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)
                 break;
            if(i!=-1){
                cur[u]=i;
                S[top++]=i;
                u=edge[i].to;
            }
            else{
                int min=n;
                for(i=head[u];i!=-1;i=edge[i].next){
                    if(edge[i].cap==0)continue;
                    if(min>dep[edge[i].to]){
                        min=dep[edge[i].to];
                        cur[u]=i;
                    }
                }
                --gap[dep[u]];
                dep[u]=min+1;
                ++gap[dep[u]];
                if(u!=start)u=edge[S[--top]].from;
            }
        }
        return res;
    }
}sap;
int n,m,s,t;
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		Dijk.init(n);
		sap.init(n);
		for(int i = 0;i<m;++i){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			Dijk.Addedge(u,v,w);
		}
		scanf("%d%d",&s,&t);
		Dijk.dijkstra(s);
		for(int i = 0;i<m;++i){
			Edge e=Dijk.edges[i];
			if(Dijk.d[e.from]+e.val==Dijk.d[e.to]){
				sap.AddEdge(e.from,e.to,1);
			}
		} 
		printf("%d\n",sap.SAP(s,t));
	}
	return 0;
} 

 

标签:head,最大,hdu3416,int,短路,dep,edge,MAXN,tol
来源: https://blog.csdn.net/qq_43472263/article/details/97753973

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

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

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

ICode9版权所有