HDU 5294 Tricks Device(多校2015 最大流+最短路啊)

來源:互聯網
上載者:User

標籤:hdu   多校2015   最大流   最短路   最小割   

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=5294


Problem DescriptionInnocent Wu follows Dumb Zhang into a ancient tomb. Innocent Wu’s at the entrance of the tomb while Dumb Zhang’s at the end of it. The tomb is made up of many chambers, the total number is N. And there are M channels connecting the chambers. Innocent Wu wants to catch up Dumb Zhang to find out the answers of some questions, however, it’s Dumb Zhang’s intention to keep Innocent Wu in the dark, to do which he has to stop Innocent Wu from getting him. Only via the original shortest ways from the entrance to the end of the tomb costs the minimum time, and that’s the only chance Innocent Wu can catch Dumb Zhang.
Unfortunately, Dumb Zhang masters the art of becoming invisible(奇門遁甲) and tricks devices of this tomb, he can cut off the connections between chambers by using them. Dumb Zhang wanders how many channels at least he has to cut to stop Innocent Wu. And Innocent Wu wants to know after how many channels at most Dumb Zhang cut off Innocent Wu still has the chance to catch Dumb Zhang.
 
InputThere 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 channels.
In the following M lines, every line must includes three numbers, and use ai、bi、li as channel i connecting chamber ai and bi(1<=ai,bi<=n), it costs li(0<li<=100) minute to pass channel i.
The entrance of the tomb is at the chamber one, the end of tomb is at the chamber N.
 
OutputOutput two numbers to stand for the answers of Dumb Zhang and Innocent Wu’s questions. 
Sample Input
8 91 2 22 3 22 4 13 5 34 5 45 8 11 6 26 7 57 8 1
 
Sample Output
2 6
 
AuthorFZUACM 
Source2015 Multi-University Training Contest 1

轉

題意:

給出n個墓室,m條路徑,一個人在1號墓室(起點),另一個人在n號墓室(終點);

起點的那個人只有通過最短路徑才能追上終點的那個人,而終點的那個人能切斷任意路徑。

 

第一問——終點那人要使起點那人不能追上的情況下可以切的最少的路徑數,輸出最少的路徑數

 

第二問——起點那人能追上終點那人的情況下,終點那人能切斷的最多的路徑數,輸出最多的路徑數

PS:

先跑最短路。

然後通過  dist[i]-dist[j] == map[j][i]

如果符合的話  map[j][i]就是 最短路中的一條邊。

然後把這些最短路的邊 建圖,跑最大流,流量是有多少邊權相同的重邊,跑出來就是最小割,也就是阻斷所有最短路的最小花費。花費是每破壞一條路為1。所以出來的值,就是破壞了多少的邊。

然後如最大流同樣的建邊,跑最短路,邊權為1,跑出來的最短路dist[n],就是  跨越邊數最少的 最短路的邊數了。

官方題解:


代碼如下:

#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的個數為yint EN;struct Edge{    int to,next,cap,flow;} edge[MAXN]; //注意是MAXMint 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\n",sap(1,n,n),m-dis2[n]);    }    return 0;}


著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

HDU 5294 Tricks Device(多校2015 最大流+最短路啊)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.