poj 2125 最小点权覆盖


Language:
Default

Destroying The Graph

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7469   Accepted: 2381   Special Judge

Description

Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that Bob tries to destroy it. In a move he may take any vertex of the graph and remove either all arcs incoming into this vertex, or all arcs outgoing from this vertex. 
Alice assigns two costs to each vertex: Wi+ and Wi-. If Bob removes all arcs incoming into the i-th vertex he pays Wi+ dollars to Alice, and if he removes outgoing arcs he pays Wi- dollars. 
Find out what minimal sum Bob needs to remove all arcs from the graph.

Input

Input file describes the graph Alice has drawn. The first line of the input file contains N and M (1 <= N <= 100, 1 <= M <= 5000). The second line contains N integer numbers specifying Wi+. The third line defines Wi- in a similar way. All costs are positive and do not exceed 106 . Each of the following M lines contains two integers describing the corresponding arc of the graph. Graph may contain loops and parallel arcs.

Output

On the first line of the output file print W --- the minimal sum Bob must have to remove all arcs from the graph. On the second line print K --- the number of moves Bob needs to do it. After that print K lines that describe Bob‘s moves. Each line must first contain the number of the vertex and then ‘+‘ or ‘-‘ character, separated by one space. Character ‘+‘ means that Bob removes all arcs incoming into the specified vertex and ‘-‘ that Bob removes all arcs outgoing from the specified vertex.

Sample Input

3 6
1 2 3
4 2 1
1 2
1 1
3 2
1 2
3 1
2 3

Sample Output

5
3
1 +
2 -
2 +

一道单纯的最小点权覆盖,但是本小白还是不会写,看了题解,然后还没看懂输出路径的部分,跪求大神指点为嘛是那样输出路径,代码如下:

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<climits>
#define MAXE 220*220
#define MAXP 220
#define Max(a,b) a>b?a:b
#define Min(a,b) a<b?a:b
using namespace std;
struct Edge
{
    int s,t,f,next;
} edge[MAXE];
int head[MAXP];
int cur[MAXP];
int pre[MAXP];
int stack[MAXE];
int sign[MAXE];
int ent;
int sum;
int n,m,s,t,supers,supert;
int num;
void add(int start,int last,int f)
{
    edge[ent].s=start;
    edge[ent].t=last;
    edge[ent].f=f;
    edge[ent].next=head[start];
    head[start]=ent++;
    edge[ent].s=last;
    edge[ent].t=start;
    edge[ent].f=0;
    edge[ent].next=head[last];
    head[last]=ent++;
}
bool bfs(int S,int T)
{
    memset(pre,-1,sizeof(pre));
    pre[S]=0;
    queue<int>q;
    q.push(S);
    while(!q.empty())
    {
        int temp=q.front();
        q.pop();
        for(int i=head[temp]; i!=-1; i=edge[i].next)
        {
            int temp2=edge[i].t;
            if(pre[temp2]==-1&&edge[i].f)
            {
                pre[temp2]=pre[temp]+1;
                q.push(temp2);
            }
        }
    }
    return pre[T]!=-1;
}
int dinic(int start,int last)
{
    int flow=0,now;
    while(bfs(start,last))
    {
        int top=0;
        memcpy(cur,head,sizeof(head));
        int u=start;
        while(1)
        {
            if(u==last)//如果找到终点结束对中间路径进行处理并计算出该流
            {
                int minn=INT_MAX;
                for(int i=0; i<top; i++)
                {
                    if(minn>edge[stack[i]].f)
                    {
                        minn=edge[stack[i]].f;
                        now=i;
                    }
                }
                flow+=minn;
                for(int i=0; i<top; i++)
                {
                    edge[stack[i]].f-=minn;
                    edge[stack[i]^1].f+=minn;
                }
                top=now;
                u=edge[stack[top]].s;
            }
            for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next) //找出从u点出发能到的边
                if(edge[i].f&&pre[edge[i].t]==pre[u]+1)
                    break;
            if(cur[u]==-1)//如果从该点未找到可行边,将该点标记并回溯
            {
                if(top==0)break;
                pre[u]=-1;
                u=edge[stack[--top]].s;
            }
            else//如果找到了继续运行
            {
                stack[top++]=cur[u];
                u=edge[cur[u]].t;
            }
        }
    }
    return flow;
}
void dfs(int S)
{
    sign[S]=1;
    for(int i=head[S]; i!=-1; i=edge[i].next)
    {
        if(edge[i].f>0&&!sign[edge[i].t])
        {
            dfs(edge[i].t);
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(head,-1,sizeof(head));
        memset(sign,0,sizeof(sign));
        ent=0;
        s=0;
        t=2*n+1;
        int cost;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&cost);
            add(i+n,t,cost);
        }
        int temp=ent;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&cost);
            add(s,i,cost);
        }
        int temp2=ent;
        for(int i=1; i<=m; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v+n,INT_MAX);
        }
        printf("%d\n",dinic(s,t));
        dfs(s);
        cout<<sign[3]<<endl;
        int cnt=0;
        for(int i=1; i<=2*n; i++)
        {
            if(!sign[i]&&i<=n)cnt++;
            else if(sign[i]&&i>n)cnt++;
        }
        printf("%d\n",cnt);
        for(int i=1; i<=2*n; i++)
        {
            if(!sign[i]&&i<=n)printf("%d -\n",i);
            else if(sign[i]&&i>n)printf("%d +\n",i-n);
        }
    }
    return 0;
}
时间: 2024-08-29 09:44:53

poj 2125 最小点权覆盖的相关文章

POJ 2125 Destroying the Graph 二分图最小点权覆盖

Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2635   Special Judge Description Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that B

POJ 2125 --Destroying The Graph【最小割解决 &quot;最小点权覆盖问题&quot; &amp;&amp; 输出解(割边集) &amp;&amp; 各种不懂】

Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7597   Accepted: 2434   Special Judge Description Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that B

poj 3308 Paratroopers 最小割 最小点权覆盖

题目链接:http://poj.org/problem?id=3308 题意: 有一个M*N的图,上面的一些点上有伞兵. 可以设置一些枪在每行或者每列上,通过射击,这行或这列的伞兵就会被消灭.每个枪的设置有一个花费,如果设置多个枪,那么花费是设置每个枪的乘积. 问消灭所有伞兵最少的花费是多少. 思路: 每个点的伞兵至少要用那一列或者那一行设置的枪去消灭,那么就可以应用点覆盖的模型.把伞兵看成是一条边,这条边至少要用一个点来覆盖. 而题目中最终花费是所有花费的乘积,那么可以用对数log(x)+lo

POJ 3308 Paratroopers (二分图最小点权覆盖 -&gt; 最小割 -&gt; 最大流)

POJ 3308 Paratroopers 链接:http://poj.org/problem?id=3308 题意:有一个N*M的方阵,有L个伞兵降落在方阵上.现在要将所有的伞兵都消灭掉,可以在每行每列装一个高射炮,如果在某行(某列)装上高射炮之后,能够消灭所有落在该行(该列)的伞兵.每行每列安高射炮有费用,问如何安装能够使得费用之积最小. 思路:首先题目要求乘积最小,将乘积对e取对数,会发现就变成了求和.然后抽象出一个二分图,每一行是x部的一个点,每个点有权值,权值为费用取ln.每一列是y部

POJ 3308 Paratroopers 最小点权覆盖 求最小割

不懂这个建模是什么原理,以后把二分图相关的东西看完再补上把= = #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #i

POJ 3308--Paratroopers【 最小点权覆盖 &amp;&amp; 最小割】

Paratroopers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7847   Accepted: 2365 Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the Mars. Recently, the commanders of the Earth are infor

poj 3308 Paratroopers(最小点权覆盖)

Paratroopers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8954   Accepted: 2702 Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the Mars. Recently, the commanders of the Earth are infor

【网络流】【最小点权覆盖】【NEERC 2003】【POJ2125】【cogs 1575】有向图破坏

1575. [NEERC 2003][POJ2125]有向图破坏 ★★★ 输入文件:destroyingthegraph.in 输出文件:destroyingthegraph.out 简单对比 时间限制:1 s 内存限制:256 MB [题目描述] Alice和Bob正在玩如下的游戏.首先Alice画一个有N个顶点,M条边的有向图.然后Bob试着摧毁它.在一次操作中他可以找到图中的一个点,并且删除它所有的入边或所有的出边. Alice给每个点定义了两个值:Wi+和Wi-.如果Bob删除了第i个点

HLG1407Leyni的游戏【最小点权覆盖集】

大意: 给你一个n行m列的矩阵 1 2 1 1 每次操作可使一整行或一整列的一个数减少1(如果是0则不变) 问最少多少次操作会使所有的数变为零 分析: 该题很像poj消灭外星人的那道题 思路也差不很多 将x轴当左集合,y轴当右集合,边权值为所在点的数字 那么一条边就代表了矩阵中的一个点 只要找出最小的权值去覆盖所有的边就能把所有的数字变为零 也就是传说中的最小点权覆盖集 最小点权覆盖集 = 最大权匹配 KM跑一遍就可以了 但是需要注意的是如果两边点的个数不相等 那么我们用虚拟点代替就可以了 代码