POJ2594-Treasure Exploration(DAG的最小路徑覆蓋 floyd)

題目鏈接

Have you ever read any book about treasure exploration? Have you ever see any film about treasure exploration? Have you ever explored treasure? If you never have such experiences, you would never know what fun treasure exploring brings to you.
Recently, a company named EUC (Exploring the Unknown Company) plan to explore an unknown place on Mars, which is considered full of treasure. For fast development of technology and bad environment for human beings, EUC sends some robots to explore the treasure.
To make it easy, we use a graph, which is formed by N points (these N points are numbered from 1 to N), to represent the places to be explored. And some points are connected by one-way road, which means that, through the road, a robot can only move from one end to the other end, but cannot move back. For some unknown reasons, there is no circle in this graph. The robots can be sent to any point from Earth by rockets. After landing, the robot can visit some points through the roads, and it can choose some points, which are on its roads, to explore. You should notice that the roads of two different robots may contain some same point.
For financial reason, EUC wants to use minimal number of robots to explore all the points on Mars.
As an ICPCer, who has excellent programming skill, can your help EUC?

Input

The input will consist of several test cases. For each test case, two integers N (1 <= N <= 500) and M (0 <= M <= 5000) are given in the first line, indicating the number of points and the number of one-way roads in the graph respectively. Each of the following M lines contains two different integers A and B, indicating there is a one-way from A to B (0 < A, B <= N). The input is terminated by a single line with two zeros.

Output

For each test of the input, print a line containing the least robots needed.

Sample Input

1 0

2 1

1 2

2 0

0 0

Sample Output

1

1

2


題意

給一個n個點,m條路的有向無環圖(DAG),找出最少的路徑,使這些路徑經過了所有的點,路徑可以走同樣的點。

思路

DAG最小路徑覆蓋的思路解釋

兩種情況的總結

把DAG轉爲二分圖,求出二分圖的最大匹配,這些匹配在DAG中,相當於可以減少一個情況。

比如1->2,本來1和2都需要一個路徑,但是1和2連接了起來,可以認爲2就不需要了,因爲有1的存在,1可以到2,前面的可以到後面的,就可以減少了1條路徑,或者說兩個路徑合爲一條。如果認爲一開始路徑個數爲n,每有1個匹配,就可以減少一個路徑,那麼最大匹配就可以達到最短路徑個數。

二分圖的匹配是左右兩點不能有公共子結點,在DAG的最小不相交路徑覆蓋問題中,DAG的每個點都只能經過一次,不能重複經過,這與二分圖的匹配是相對應的。

DAG的最小可相交路徑覆蓋,也是求最大匹配,但是由於走過的點可以再走,這與匹配就不太符合。可以通過floyd增加可以走的所有邊,例如1->2,2->3,有這兩條邊,所以1也可以走到3,所以添加一條邊1->3,這樣添加完後,1走到3就不需要看2有沒有走過,這就符合了走過的點可以再走的要求。這樣就轉化爲最小不相交路徑問題,


#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N = 510;
int ln,rn,n,m;
int a[N][N],vis[N],link[N];

int dfs(int L)
{
    for(int R=1;R<=rn;R++){
        if(a[L][R]&&!vis[R]){
            vis[R] = 1;
            if(link[R]==-1||dfs(link[R])){
                link[R] = L;
                return 1;
            }
        }
    }
    return 0;
}

int hungary()
{
    int ans = 0;
    memset(link,-1,sizeof(link));
    for(int i=1;i<=ln;i++){
        memset(vis,0,sizeof(vis));
        if(dfs(i)) ans++;
    }
    return ans;
}

int main(){
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0&&m==0) break;
        ln = rn = n;
        memset(a,inf,sizeof(a));
        for(int i=1;i<=m;i++){
            int x,y; scanf("%d%d",&x,&y);
            a[x][y] = 0;
        }
        for(int i=1;i<=n;i++) a[i][i] = 0;//floyd算法,任意兩點之間的距離
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(a[i][k]+a[k][j]<a[i][j])
                        a[i][j] = a[i][k] + a[k][j];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(a[i][j]==inf||i==j) a[i][j] = 0;//0表示在二分圖中沒有連接
                else a[i][j] = 1;                  //自己跟自己或者距離爲inf都不連
            }
        printf("%d\n",n-hungary());
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章