【NEERC 2003】有向图破坏

【题目描述】

Alice和Bob正在玩如下的游戏。首先Alice画一个有N个顶点,M条边的有向图。然后Bob试着摧毁它。在一次操作中他可以找到图中的一个点,并且删除它所有的入边或所有的出边。

Alice给每个点定义了两个值:Wi+和Wi-。如果Bob删除了第i个点所有的入边他要给Alice付Wi+元,如果他删除了所有的出边就需要给Alice付Wi元。

找到Bob删除图中所有边需要的最小花费。

【输入格式】

输入数据描述了Alice画下的图。

输入文件的第一行有两个数N,M(1<=N<=100,1<=M<=5000)。第二行有N个整数,描述了N个点的Wi+,同样的第三行是这N个点的Wi-。所有的费用都是正数并且不超过10^6。接下来的M行每行有两个数,代表有向图中相应的一条边。

【输出格式】

输出一行一个整数,即Bob的最小花费。

【分析】

很容易想到,把每个点拆成两个点,一个控制出边,一个控制入边,保留原边后很明显的一个最小权点覆盖集,Dinic就行了。

 

 1 #include <cstdlib>

 2 #include <iostream>

 3 #include <cstring>

 4 #include <cstdio>

 5 #include <queue>

 6 const int maxn=500;

 7 const int INF=10000*10000;

 8 using namespace std;

 9 struct tu

10 {

11        int c,f;

12        tu(){c=0;f=0;}

13 }maps[maxn][maxn];

14 int dist[maxn],n,m;

15 

16 void Dinic();

17 bool BFS();//构建层次网络 

18 int dfs(int v,int low);

19 

20 int main()

21 {

22     int i;

23     //文件操作

24     freopen("destroyingthegraph.in","r",stdin);

25     freopen("destroyingthegraph.out","w",stdout);

26     memset(maps,0,sizeof(maps));

27     

28     scanf("%d%d",&n,&m);//n个点,m条边 

29     

30     for (i=1;i<=n;i++) scanf("%d",&maps[i+n][2*n+1].c);//w+

31     for (i=1;i<=n;i++) scanf("%d",&maps[0][i].c);//w-

32     

33     for (i=1;i<=m;i++) 

34     {

35         int u,v;

36         scanf("%d%d",&u,&v);

37         maps[u][v+n].c=INF;

38     }

39     Dinic();

40     return 0;

41 }

42 void Dinic()

43 {

44      int flow=0;

45      while ( BFS() )

46      {

47            int temp=0;

48            if (temp=dfs(0,INF)) flow+=temp;

49      }

50      printf("%d\n",flow);

51 }

52 bool BFS()//层次网络

53 {

54      queue<int>Q;

55      int i;

56      memset(dist,-1,sizeof(dist));

57      dist[0]=0;

58      Q.push(0);

59      while (!Q.empty())

60      {

61            int u=Q.front();Q.pop();

62            for (i=0;i<=(2*n+1);i++)

63            {

64                int v=i;

65                if(maps[u][v].c-maps[u][v].f>0 && dist[v]==-1)

66                {

67                   dist[v]=dist[u]+1;

68                   Q.push(v);

69                } 

70            } 

71      }

72      return (dist[(2*n)+1]!=-1);

73 } 

74 int dfs(int u,int low)

75 {

76      if (u==(2*n)+1 || low==0) return low;

77      int flow=0,f,i;

78      for (i=0;i<=(2*n)+1;i++)

79      {

80          int v=i;

81          if (maps[u][v].c>maps[u][v].f && dist[v]==dist[u]+1)

82          {

83              if (f=dfs(i,min(low,maps[u][v].c-maps[u][v].f)))

84              {

85                  maps[u][v].f+=f;

86                  maps[v][u].f-=f;

87                  low-=f;

88                  flow+=f;

89                  if (low==0) break;

90              }

91          }

92      }

93      return flow;

94 }
View Code

 

你可能感兴趣的:(2003)