HDU 5294 Tricks Device(多校2015最大流+最短絡ですね)


テーマリンク:http://acm.hdu.edu.cn/showproblem.php?pid=5294
Problem Description
Innocent Wu followows Dumb Zhang into a ancint tomb.InnocentWu’s at the entrance of the tomb while Dumb Zhang’s the end of it.The tomb is made up of madmade up of many chambers to,the totototalnumberis.Anstathe the the Anstammmttttttttchachachachaneneneneneneconconconconconconconconconconconconconconconconconcons s s s s s s s s s s s s s s s s s s s s s.thethethethethethethethe thethethethethe atttwers of some questions,however,it’s Dumb Zhang’s intent to keep Innocent Wu in the dark,to do which he has to stop Innocent Wu from getting him.Only via the original shot ways the ntrance to the end of the tomb costints mintch
Unfortunally、Dumb Zhang masters the art of becomping invisible(奇門遁甲)とtricks devices of this tomb、he can cut off the connections between chambers by using them.Dumb Zhang wanders how many chanelst least he has to stop Innocent Wu.And Innocent Wu to know to know hofter howmany chanelst chanelst motch
 
Input
The re are multiple test cases.Please process till EOF.
For each case,the first line must includes two integers,N(<=2000),M(<=60000).N is the total number of the chambers,M is the total number of the chanels.
In the follwing M line as、evry line must includes three numbers、and use ai、bi、lias chanel i connecting chamber ai and bi(1<=ai、bi<=n)、it cots li(0The entrance of the tomb is the chamber one、the end of tomb ist the chamber N.
 
Output
Output two numbers to stand for the answers of Dumb Zhang and Innocent Wu's questions.
 
Sample Input

   
   
   
   
8 9 1 2 2 2 3 2 2 4 1 3 5 3 4 5 4 5 8 1 1 6 2 6 7 5 7 8 1
 
Sample Output

   
   
   
   
2 6
 
Author
FZUACM
 
ソurce
2015 Multi-University Training Conteest 1
回転
件名:
nつの墓室を与えて、m条の道、一人は1番の墓室(起点)にいて、もう一人はn番の墓室(終点)にいます.
スタート地点のあの人は最短ルートでゴールインできる人だけで、ゴールのその人は任意のパスを切断することができます.
 
一番目の質問——終点の人は起点の人を追いつけないようにします.一番近いルート数を切って、一番少ないパス数を出力します.
 
起点の人がゴールに追いつくことができる場合、ゴールの人が切ることができる一番多いパス数は、一番多いパス数を出力します.
PS:
先走が一番短絡的です
そして通過します dist[i]-dist[j]==map[j][i]
もし合ったら map[j][i]は最も短絡の中の一つです.
そして、これらの最も短絡した辺を図を立てて、最大の流れを走ります.流量はどれぐらいの辺の権利が同じですか?走り出すのは最小の切断です.つまり、すべての一番短絡を遮断する最小の費用です.費用は破壊するごとに1つの道があります.だから出てくる値は、どれぐらいの辺を壊したかです.
そして最大流のように建辺して、一番短絡して、辺権は1で、走出した一番短絡dist[n]は 辺の数が一番少ない一番短絡的な辺の数を超えました.
公式の問題:
HDU 5294 Tricks Device(多校2015 最大流+最短路啊)_第1张图片
コードは以下の通りです
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f

#define MAXN 800047//      
#define MAXM 2247//      

int head[MAXM], pre[MAXM];
int dep[MAXM], cur[MAXM], gap[MAXM];//gap[x]=y :       dep[i]==x    y
int EN;
struct Edge
{
    int to,next,cap,flow;
} edge[MAXN]; //   MAXM
int tol;
int k, c, m;
int s, e;//  ,  
int map[MAXM][MAXM];
int cost1[MAXM][MAXM], cost2[MAXM][MAXM];

int num[MAXM][MAXM];//    ,>1     
//  ,       ,       
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;
}

void Dijkstra(int s, int n, int cost[][MAXM], int dis[MAXM])
{
    //int dis[MAXM];//           
    int mark[MAXM];//        
    int i, j, k;
    for(i = 1; i <= n; i++)
    {
        mark[i] = 0;//       ,          
        dis[i] = INF;
    }
    mark[s] = 1;//start     
    dis[s] = 0;// start         0
    int MIN;//       。
    for(i = 1; i <= n; i++)
    {
        k = 1;//      
        MIN = INF;
        for(j = 1; j <= n; j++)
        {
            if(!mark[j] && dis[j] < MIN)//        ,        
            {
                MIN = dis[j] ;
                k = j;
            }
        }
        mark[k] = 1;//      
        for(j = 1; j <= n; j++)
        {
            if(!mark[j] && dis[j]>dis[k] + cost[k][j])//           
            {
                dis[j] = dis[k] + cost[k][j];
            }
        }
    }
}

void init()
{
    memset(head,-1,sizeof(head));
    memset(cost1,INF,sizeof(cost1));
    memset(cost2,INF,sizeof(cost2));
    memset(num,0,sizeof(num));
    EN = 0;
}

int main()
{
    int n, m;
    int u, v, w;
    int dis1[MAXM], dis2[MAXM];
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i = 1; i <= n; i++)
        {
            cost1[i][i] = 0;
        }
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            if(cost1[u][v] > w)
            {
                cost1[u][v] = w;
                cost1[v][u] = w;
                num[u][v] = 1;
                num[v][u] = 1;
            }
            else if(cost1[u][v] == w)//  
            {
                num[u][v]++;
                num[v][u]++;
            }
        }
        Dijkstra(1,n,cost1,dis1);
        for(int i = 1; i <= n; i++)
        {
            cost2[i][i] = 0;
        }
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                if(i != j)
                {
                    if(dis1[i] - dis1[j] == cost1[i][j])//     
                    {
                        cost2[j][i] = 1;
                        addedge(j,i,num[i][j]);
                    }
                }
            }
        }
        Dijkstra(1,n,cost2,dis2);
        printf("%d %d
",sap(1,n,n),m-dis2[n]); } return 0; }