天天看點

Cogs 728. [網絡流24題] 最小路徑覆寫問題

  1. [網絡流24題] 最小路徑覆寫問題

    ★★☆ 輸入檔案:path3.in 輸出檔案:path3.out 評測插件

    時間限制:1 s 記憶體限制:128 MB

    算法實作題8-3 最小路徑覆寫問題(習題8-13)

    ´問題描述:

    給定有向圖G=(V,E)。設P是G的一個簡單路(頂點不相交)的集合。如果V中每個

    頂點恰好在P的一條路上,則稱P是G的一個路徑覆寫。P中路徑可以從V的任何一個頂

    點開始,長度也是任意的,特别地,可以為0。G的最小路徑覆寫是G的所含路徑條數最少

    的路徑覆寫。

    設計一個有效算法求一個有向無環圖G的最小路徑覆寫。

    提示:

    設V={1,2,… ,n},構造網絡G1=(V1,E1)如下:

    每條邊的容量均為1。求網絡G1的(x0,y0)最大流。

    ´程式設計任務:

    對于給定的給定有向無環圖G,程式設計找出G的一個最小路徑覆寫。

    ´資料輸入:

    由檔案input.txt提供輸入資料。檔案第1行有2個正整數n和m。n是給定有向無環圖

    G的頂點數,m是G的邊數。接下來的m行,每行有2個正整數i 和j,表示一條有向邊(i,j)。

    ´結果輸出:

    程式運作結束時,将最小路徑覆寫輸出到檔案output.txt中。從第1行開始,每行輸出

    一條路徑。檔案的最後一行是最少路徑數。

    輸入檔案示例

    input.txt

    11 12

    1 2

    1 3

    1 4

    2 5

    3 6

    4 7

    5 8

    6 9

    7 10

    8 11

    9 11

    10 11

    輸出檔案示例

    output.txt

    1 4 7 10 11

    2 5 8

    3 6 9

    3

    資料範圍:

    1<=n<=150,1<=m<=6000

/*
最小路徑覆寫數=V-最大流.
然後拆點建圖.
搞一個超級源點和彙點跑dinic.
輸出的時候在殘餘網絡裡找貢獻邊.
恩就是這樣. 
*/
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define MAXN 10001
using namespace std;
struct data{int v,next,c;}e[MAXN*4];
int n,m,max1=e9,ans,tot,cut=,dis[MAXN*2],head[MAXN*2],next[MAXN*2];
bool in[MAXN*2];
inline int read()
{
    int x=,f=;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-,ch=getchar();
    return x*f;
}
void add(int u,int v,int x)
{
    e[++cut].v=v;
    e[cut].c=x;
    e[cut].next=head[u];
    head[u]=cut;
}
bool bfs()
{
    memset(dis,-,sizeof dis);
    queue<int>q;
    q.push();
    dis[]=;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v]==-&&e[i].c)
            {
                dis[v]=dis[u]+;
                q.push(v);
            }
        }
    }
    return dis[n*2+]!=-;
}
int dfs(int u,int y)
{
    if(u==n*2+) return y;
    int rest=;
    for(int i=head[u];i&&rest<y;i=e[i].next)
    {
        int v=e[i].v;
        if(dis[v]==dis[u]+&&e[i].c)
        {
            int x=dfs(v,min(e[i].c,y-rest));
            rest+=x;
            e[i].c-=x;
            e[i^].c+=x;
        }
    }
    if(!rest) dis[u]=-;
    return rest;
}
void print()
{
    for(int u=;u<=n;u++)
      for(int i=head[u];i;i=e[i].next)
      {
          int v=e[i].v;
          if(e[i].c==max1-) in[v-n]=true,next[u]=v-n;
      }
    for(int i=;i<=n;i++)
    {
        int x=i;
        if(!in[x])
        {
            while(x) printf("%d ",x),x=next[x];
            printf("\n");
        }
    }
}
void dinic(int s,int t)
{
    while(bfs()) ans+=dfs(s,max1);
    print();
    printf("%d\n",n-ans);
    return ;
}
int main()
{
    freopen("path3.in","r",stdin);
    freopen("path3.out","w",stdout); 
    int x,y;
    n=read(),m=read();
    for(int i=;i<=n;i++) add(,i,),add(i,,);
    for(int i=;i<=n;i++) add(i+n,n*2+,),add(*n+,i+n,);
    for(int i=;i<=m;i++)
    {
        x=read(),y=read();
        add(x,y+n,max1),add(y+n,x,);
    }
    dinic(,n*2+);
    return ;
}
           

轉載于:https://www.cnblogs.com/nancheng58/p/10068143.html