hdu3416 Marriage Match IV【最短路+最大流】

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

题目描述:求起点到终点一共有多少完全不同的最短路径(最短路径之间不能有公共边)

思路:先用dijkstra求出起点到终点的最短路,然后用可以成为最短路径的边(dis[终]-dis[始]==权值)建立网络,容量为1。最后只需求出以起点为源点终点为汇点的最大流即可

#include <iostream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <sstream>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <climits>
using namespace std;
#define XINF INT_MAX
#define INF 1<<30
#define MAXN 1000+10
#define eps 1e-8
#define zero(a) fabs(a)<eps
#define sqr(a) ((a)*(a))
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define PF(X) push_front(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
#define PI  acos(-1.0)
#define test puts("OK");
#define _ ios_base::sync_with_stdio(0);cin.tie(0);
typedef long long ll;
typedef pair<int,int> PII;
typedef priority_queue<int,vector<int>,greater<int> > PQI;
typedef vector<PII> VII;
typedef vector<int> VI;
#define X first
#define Y second

int V,E;
VII G2[MAXN];
int d[MAXN];

void dijkstra(int s)
{
    priority_queue<PII,VII,greater<PII> > Q;
    fill(d,d+V,INF);
    d[s]=0;
    Q.push(MP(d[s],s));
    while(!Q.empty())
    {
        PII p=Q.top();Q.pop();
        int v=p.Y;
        if(d[v]<p.X)
            continue;
        REP(i,G2[v].size())
        {
            PII e=G2[v][i];
            if(d[e.X]>d[v]+e.Y)
            {
                d[e.X]=d[v]+e.Y;
                Q.push(MP(d[e.X],e.X));
            }
        }
    }
}

struct edge
{
    int to;    //终点
    int cap;   //容量
    int rev;   //反向边
    edge(int t,int c,int r){to=t;cap=c;rev=r;}
};

vector<edge> G[MAXN];   //存图
int level[MAXN];        //顶点到源点的距离标号
int iter[MAXN];         //当前弧,在其之前的边已经没有用了
int S,T;

void add_edge(int from,int to,int cap)
{
    edge e1(to,cap,G[to].size());
    G[from].PB(e1);
    edge e2(from,0,G[from].size()-1);
    G[to].PB(e2);
}

//通过BFS计算从源点出发的距离标号
void bfs(int s)
{
    CLR(level,-1);
    queue<int> Q;
    level[s]=0;
    Q.push(s);
    while(!Q.empty())
    {
        int v=Q.front();
        Q.pop();
        REP(i,G[v].size())
        {
            edge &e=G[v][i];
            if(e.cap>0 && level[e.to]<0)
            {
                level[e.to]=level[v]+1;
                Q.push(e.to);
            }
        }
    }
}

int dfs(int v,int t,int f)
{
    if(v==t)
        return f;
    for(int &i=iter[v];i<G[v].size();i++)
    {
        edge &e=G[v][i];
        if(e.cap>0 && level[v]<level[e.to])
        {
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0)
            {
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s,int t)
{
    int flow=0;
    while(1)
    {
        bfs(s);
        if(level[t]<0)
            return flow;
        CLR(iter,0);
        int f;
        while((f=dfs(s,t,INF))>0)
            flow+=f;
    }
}

int main()
{_
    int P;
    scanf("%d",&P);
    while(P--)
    {
        CLR(G,0);CLR(G2,0);
        scanf("%d%d",&V,&E);
        REP(i,E)
        {
            int u,v,c;
            scanf("%d%d%d",&u,&v,&c);
            u--;v--;
            if(u!=v)
                G2[u].PB(MP(v,c));
        }
        scanf("%d%d",&S,&T);
        S--;T--;
        dijkstra(S);
        if(d[T]==INF)
        {
            printf("0\n");
            continue;
        }
        REP(v,V)
        {
            REP(i,G2[v].size())
            {
                PII e=G2[v][i];
                int u=e.X,cost=e.Y;
                if(d[u]-d[v]==cost)
                    add_edge(v,u,1);
            }
        }
        printf("%d\n",max_flow(S,T));
    }
    return 0;
}
时间: 2025-01-13 11:22:59

hdu3416 Marriage Match IV【最短路+最大流】的相关文章

hdu3416 Marriage Match IV 最短路+ 最大流

此题的大意:给定一幅有向图,求起点到终点(都是固定的)的不同的最短路有多少条.不同的最短路是说不能有相同的边,顶点可以重复.并且图含有平行边. 看了题以后,就想到暴力,但是暴力往往是不可取的.(暴力的最坏情况下的时间复杂度是O(n^3)).我说的暴力是求一次最短路以后,把最短路上的边全部去掉(权值设为INF). 最短路可以有很多条,但是最短路的值只有一个.根据这个,我们可以判断某条边是否在最短路上. 建图(单向边),求最短路,起点就是输入的起点.枚举每一条边,如果满足dist[i]+Map[i]

HDU3416 Marriage Match IV(spfa+最大流SAP)

Marriage Match IV Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2391    Accepted Submission(s): 722 Problem Description Do not sincere non-interference. Like that show, now starvae also take

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-inter

hdu3416 Marriage Match IV(最短路+网络流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416 题意: 给出含n个点.m条有向边的图,每条边只能走一次,给出起点和终点,求起点到终点的最短路径有多少条. 思路: 题目要求是最短路径,当然需要求出最短路,用Dijkstra就可以了,然后我们需要构造网络流的图.将能组成最短路的边加入图中,容量设为1,注意能组成最短路的边是满足dis[u] + edge[i].dist == dis[v] 的边,其中u是边的起点,v是边的终点,dis[]保存的是

hdu3461Marriage Match IV 最短路+最大流

//给一个图.给定起点和终点,仅仅能走图上的最短路 //问最多有多少种走的方法.每条路仅仅能走一次 //仅仅要将在最短路上的全部边的权值改为1.求一个最大流即可 #include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> using namespace std ; const int inf = 0x3f3f3f3f ; const

HDU 3416 Marriage Match IV(最短路+最大流)

HDU 3416 Marriage Match IV 题目链接 题意:给一个有向图,给定起点终点,问最多多少条点可以重复,边不能重复的最短路 思路:边不能重复,以为着每个边的容量就是1了,最大流问题,那么问题只要能把最短路上的边找出来,跑一下最大流即可,判断一条边是否是最短路上的边,就从起点和终点各做一次dijstra,求出最短路距离后,如果一条边满足d1[u] + d2[v] + w(u, v) == Mindist,那么这条边就是了 代码: #include <cstdio> #inclu

hdu 3416 Marriage Match IV (最短路+最大流)

hdu 3416 Marriage Match IV 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 a

HDU 3416 Marriage Match IV(最短路+网络流之最大流)

题目地址:HDU 3416 这道题WA了一天半...最终才发现是我一直习惯性的将isap的表示上界的变量直接表示成sink+1了...但是在这道题里汇点sink不一定是最后一个点...sad... 这题可以有两种方法做,一种是求两次最短路,d1表示所有点到源点的最短距离,再求一次用d2表示所有点到汇点的最短距离.然后根据公式d1[u]+d2[v]+w==d1[sink]判断是否属于最短路中的一条边. 还有一种是只求一次最短路,直接用d[v]==d[u]+w来判断是否是可以到达源点的最短路,如果可

Marriage Match IV (hdu 3416 网络流+spfa最短路)

Marriage Match IV Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2275    Accepted Submission(s): 691 Problem Description Do not sincere non-interference. Like that show, now starvae also take