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

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

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


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
 题目大意: 求有多少条没有公共边的最短路
 题解:先跑一边单源最短路,然后遍历所有的边,对于edge[i],如果dis[edge[i].from] + edge[i].w = dis[edge[i].to],说明该边在在最短路中,在新图中加入该边。
   然后跑一遍每条边cap均为1的最大流即可。一开始跑的spfa+dinic,疯狂TLE,调试半天后改成spfa+isap一发AC....
   不是很懂是这道题卡dinic还是我写臭了....
 
/*
AC代码
spfa+isap
*/
#include <bits/stdc++.h>
using namespace std;

int T,n,m;
int s,t;

const int MAXN = 100010;
const int MAXM = 400010;
const int INF = 0x3f3f3f3f;
struct Edge
{
    int to,next,cap,flow;
} edge[MAXM]; 
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],cur[MAXN];
void init()
{
    tol = 0;
    memset(head, -1,sizeof(head));
}
void addedge(int u,int v,int w,int rw = 0){
             edge[tol].to = v; edge[tol].cap = w;edge[tol].flow = 0;
                 edge[tol].next = head[u]; head[u] = tol++;
             edge[tol].to = u; edge[tol].cap = rw;edge[tol].flow = 0;
                 edge[tol].next = head[v]; head[v] = tol++;
}
int Q[MAXN];
void BFS(int start,int end)
{
    memset(dep, -1,sizeof(dep));
    memset(gap,0,sizeof(gap));
    gap[0] = 1;
    int front = 0, rear = 0;
    dep[end] = 0;
    Q[rear++] = end;
    while(front != rear)
    {
        int u = Q[front++];
        for(int i = head[u]; i != -1;i = edge[i].next){
                int v = edge[i].to;
                if(dep[v] != -1)continue;
                    Q[rear++] = v;
                    dep[v] = dep[u] + 1;
                    gap[dep[v]]++;
        }
}
}
int S[MAXN];
int sap(int start,int end,int N)
{
    BFS(start,end);
    memcpy(cur,head,sizeof(head));
    int top = 0;
    int u = start;
    int ans = 0;
    while(dep[start] < N)
    {
        if(u == end)
        {
            int Min = INF;
            int inser;
            for(int i = 0; i < top; i++)
                if(Min > edge[S[i]].cap -edge[S[i]].flow)
                {
                    Min = edge[S[i]].cap -edge[S[i]].flow;
                    inser = i;
                }
            for(int i = 0; i < top; i++)
            {
                edge[S[i]].flow += Min;
                edge[S[i]^1].flow -= Min;
            }
            ans += Min;
            top = inser;
            u = edge[S[top]^1].to;
            continue;

        }
        bool flag = false;
        int v;
        for(int i = cur[u]; i != -1; i = edge[i].next)
        {
            v = edge[i].to;
            if(edge[i].cap -edge[i].flow && dep[v]+1 == dep[u])
            {
                flag = true;
                cur[u] = i;
                break;
            }
        }
        if(flag)
        {
            S[top++] = cur[u];
            u = v;
            continue;
        }
        int Min = N;
        for(int i = head[u]; i != -1; i = edge[i].next)
            if(edge[i].cap -edge[i].flow && dep[edge[i].to] < Min)
            {
                Min = dep[edge[i].to];
                cur[u] = i;
            }
        gap[dep[u]]--;
        if(!gap[dep[u]])
            return ans;
        dep[u] = Min + 1;
        gap[dep[u]]++;
        if(u != start)
            u = edge[S[--top]^1].to;
    }
    return ans;
}

struct K
{
    int from,next,to,w;
} e[MAXM];
int dis[MAXN],vis[MAXN];

queue <int> q;
int c[MAXN];
void spfa(int s,int t,int n)
{
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(c,0,sizeof(c));
    vis[s] = true;
    dis[s] = 0;
    while(!q.empty())
        q.pop();
    q.push(s);
    c[s] = 1;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u]; i != -1; i = e[i].next)
        {
            int v = e[i].to,w = e[i].w;
            if (dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                if (!vis[v])
                {
                    vis[v] = 1;
                    if (++c[v] > n)
                        return;
                    q.push(v);
                }
            }
        }
    }
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        int tt = 0;
        memset(head,-1,sizeof(head));
        for (int i = 0; i < m; ++i)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if (u == v)
                continue;
            e[tt] = K{u,head[u],v,w};
            head[u] = tt++;
        }
        scanf("%d%d",&s,&t);
        spfa(s,t,n);
        init();
        for (int i = 0; i < tt; ++i)
        {
            int u = e[i].from,v = e[i].to,w = e[i].w;
            if (dis[u] + w == dis[v])
            {
                addedge(u,v,1);
            }
        }
        int flow = sap(s,t,n);
        printf("%d
",flow);
    }
    return 0;
}

下面是TLE的spfa+dinic:

//TLE spfa+dinic
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2010;
const int MAXM = 120001;
const int INF = 0x3f3f3f3f;
int T,n,m;
int s,t;
struct Edge
{
    int to,next,cap,flow;
} edge[MAXM]; 
int tol;
int head[MAXN];
void init()
{
    tol = 2;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw = 0)
{
    edge[tol].to = v;
    edge[tol].cap = w;
    edge[tol].flow = 0;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = rw;
    edge[tol].flow = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}
int Q[MAXN];
int dep[MAXN],cur[MAXN],sta[MAXN];
bool bfs(int s,int t,int n)
{
    int front = 0,tail = 0;
    memset(dep,-1,sizeof(dep[0])*(n+1));
    dep[s] = 0;
    Q[tail++] = s;
    while(front < tail)
    {
        int u = Q[front++];
        for(int i = head[u]; i != - 1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(edge[i].cap > edge[i].flow && dep[v] == - 1)
            {
                dep[v] = dep[u] + 1;
                if(v == t)
                    return true;
                Q[tail++] = v;
            }
        }
    }
    return false;
}
int dinic(int s,int t,int n)
{
    int maxflow = 0;
    while(bfs(s,t,n))
    {
        for(int i = 0; i < n; i++)
            cur[i] = head[i];
        int u = s, tail = 0;
        while(cur[s] != - 1)
        {
            if(u == t)
            {
                int tp = INF;
                for(int i = tail - 1; i >= 0; i--)
                    tp = min(tp,edge[sta[i]].cap - edge[sta[i]].flow)
                         ;
                maxflow += tp;
                for(int i = tail - 1; i >= 0; i--)
                {
                    edge[sta[i]].flow += tp;
                    edge[sta[i]^1].flow -= tp;
                    if(edge[sta[i]].cap - edge[sta[i]].flow == 0)
                        tail = i;
                }
                u = edge[sta[tail]^1].to;
            }
            else if(cur[u] != - 1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to])
            {
                sta[tail++] = cur[u];
                u = edge[cur[u]].to;
            }
            else
            {
                while(u != s && cur[u] == - 1)
                    u = edge[sta[--tail]^1].to;
                cur[u] = edge[cur[u]].next;
            }
        }
    }
    return maxflow;
}

struct K{
    int from,next,to,w;
}e[MAXM];
int dis[MAXN],vis[MAXN];

queue <int> q;
int c[MAXN];
void spfa(int s,int t,int n){
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(c,0,sizeof(c));
    vis[s] = true;
    dis[s] = 0;
    while(!q.empty()) q.pop();
    q.push(s);
    c[s] = 1;
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u];i != -1;i = e[i].next){
            int v = e[i].to,w = e[i].w;
            if (dis[v] > dis[u] + w){
                dis[v] = dis[u] + w;
                if (!vis[v]){
                    vis[v] = 1;
                    if (++c[v] > n) return;
                    q.push(v);
                }
            }
        }
    }
}

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        int tt = 0;
        memset(head,-1,sizeof(head));
        for (int i = 0;i < m;++i){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if (u == v) continue;
            e[tt] = K{u,head[u],v,w};
            head[u] = tt++;
        }
        scanf("%d%d",&s,&t);
        spfa(s,t,n);
        init();
        for (int i = 0;i < tt;++i){
            int u = e[i].from,v = e[i].to,w = e[i].w;
            if (dis[u] + w == dis[v]){
                addedge(u,v,1);
            }
        }
        int flow = dinic(s,t,n);
        printf("%d
",flow);
    }
    return 0;
}