Random Maze (hdu 4067 最小费用流 好题 贪心思想建图)

Random Maze

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 1373    Accepted Submission(s): 514

Problem Description

In the game “A Chinese Ghost Story”, there are many random mazes which have some characteristic:

1.There is only one entrance and one exit.

2.All the road in the maze are unidirectional.

3.For the entrance, its out-degree = its in-degree + 1.

4.For the exit, its in-degree = its out-degree + 1.

5.For other node except entrance and exit, its out-degree = its in-degree.

There is an directed graph, your task is removing some edge so that it becomes a random maze. For every edge in the graph, there are two values a and b, if you remove the edge, you should cost b, otherwise cost a.

Now, give you the information of the graph, your task if tell me the minimum cost should pay to make it becomes a random maze.

Input

The first line of the input file is a single integer T.

The rest of the test file contains T blocks.

For each test case, there is a line with four integers, n, m, s and t, means that there are n nodes and m edges, s is the entrance‘s index, and t is the exit‘s index. Then m lines follow, each line consists of four integers, u, v, a and b, means that there
is an edge from u to v.

2<=n<=100, 1<=m<=2000, 1<=s, t<=n, s != t. 1<=u, v<=n. 1<=a, b<=100000

Output

For each case, if it is impossible to work out the random maze, just output the word “impossible”, otherwise output the minimum cost.(as shown in the sample output)

Sample Input

2
2 1 1 2
2 1 2 3
5 6 1 4
1 2 3 1
2 5 4 5
5 3 2 3
3 2 6 7
2 4 7 6
3 4 10 5

Sample Output

Case 1: impossible
Case 2: 27

Source

The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online
Contest

Recommend

lcy   |   We have carefully selected several similar problems for you:  4064 4062 4063 4065 4066

这一题建图很巧妙,自己想不出来,解题思路参考这位大神Here

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define mod 1000000009
#define INF 100000
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

const int MAXN = 105;
const int MAXM = 100000;

struct Edge
{
    int to,next,cap,flow,cost;
}edge[MAXM];

int head[MAXN],tol;
int pre[MAXN],dis[MAXN],MIN[MAXN];
bool vis[MAXN];
int N;
int n,m,s,t;

int in[MAXN],out[MAXN];

void init(int n)
{
    N=n;
    tol=0;
    memset(head,-1,sizeof(head));
}

void addedge(int u,int v,int cap,int cost)
{
    edge[tol].to=v;
    edge[tol].cap=cap;
    edge[tol].cost=cost;
    edge[tol].flow=0;
    edge[tol].next=head[u];
    head[u]=tol++;
    edge[tol].to=u;
    edge[tol].cap=0;
    edge[tol].cost=-cost;
    edge[tol].flow=0;
    edge[tol].next=head[v];
    head[v]=tol++;
}

bool spfa(int s,int t)
{
    queue<int>q;
    for (int i=0;i<N;i++)
    {
        dis[i]=INF;
        vis[i]=false;
        pre[i]=-1;
    }
    MIN[s]=INF;
    dis[s]=0;
    vis[s]=true;
    q.push(s);
    while (!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=false;
        for (int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost)
            {
                dis[v]=dis[u] + edge[i].cost;
                pre[v]=i;
                MIN[v]=min(edge[i].cap-edge[i].flow,MIN[u]);
                if (!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
    }
    return pre[t]!=-1;
}

//返回的是最大流,cost存的是最小费用
int minCostMaxflow(int s,int t,int &cost)
{
    int flow=0;
    cost=0;
    while (spfa(s,t))
    {
        int Min=MIN[t];
        for (int i=pre[t];i!=-1;i=pre[edge[i^1].to])
        {
            edge[i].flow+=Min;
            edge[i^1].flow-=Min;
            cost+=edge[i].cost*Min;
        }
        flow+=Min;
    }
    return flow;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin);
#endif
    int i,j,T;
    int u,v,a,b,sum,Case=1;
    sf(T);
    while (T--)
    {
        sum=0;
        memset(in,0,sizeof(in));
        scanf("%d%d%d%d",&n,&m,&s,&t);
        init(n+2);
        for (i=0;i<m;i++)
        {
            scanf("%d%d%d%d",&u,&v,&a,&b);
            if (a<=b)
            {
                sum+=a;
                addedge(v,u,1,b-a);
                --in[u];++in[v];
            }
            else
            {
                sum+=b;
                addedge(u,v,1,a-b);
//                in[v]++;in[u]--;
            }
        }
        in[s]++;
        in[t]--;
        int tmp=0;
        for (int i=1;i<=n;i++)
        {
            if (in[i]>0)
                addedge(0,i,in[i],0);
            else
                addedge(i,N-1,-in[i],0),tmp-=in[i];
        }
        int x,ans;
        x=minCostMaxflow(0,N-1,ans);
        pf("Case %d: ", Case++);
        if (x==tmp) printf("%d\n",ans+sum);
        else printf("impossible\n");
    }
    return 0;
}
/*
2
2 1 1 2
2 1 2 3
5 6 1 4
1 2 3 1
2 5 4 5
5 3 2 3
3 2 6 7
2 4 7 6
3 4 10 5
*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 23:22:27

Random Maze (hdu 4067 最小费用流 好题 贪心思想建图)的相关文章

POJ 3422 HDU 2686,3376 费用流拆点建图

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3376 http://acm.hdu.edu.cn/showproblem.php?pid=2686 http://poj.org/problem?id=3422 POJ 3422为从矩阵左上角走到右下角,最多走k次,每个格子里的数字只能算一次,后面可以重复经过,求经过的各个数字的和的最大值. 拆点,入点向出点连流量为1,费用为当前格子负值的边,向下方,右方连边,流量为k,费用为0,起点连流量为1,

HDU 5695 ——Gym Class——————【贪心思想,拓扑排序】

Gym Class Time Limit: 6000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 768    Accepted Submission(s): 309 Problem Description 众所周知,度度熊喜欢各类体育活动. 今天,它终于当上了梦寐以求的体育课老师.第一次课上,它发现一个有趣的事情.在上课之前,所有同学要排成一列, 假设最开始每个人有

hdu 3639 Hawk-and-Chicken 【强连通分量+反向建图dfs】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3639 题意:有n个人,m条边,每条边代表u给v投一票,票可以传递,比如A->B,B->C,这时C可以得到2票,求出得到最大票数的人有哪些. 分析:从一个强连通到另一个强连通分量的贡献为这两个强连通分量大小和减一.显然票数最大的人在图的端点. 将缩点后的图方向,可以得到一些入度为0的点,用DFS可以求出这些点的票数,最后去求出最大票数. 代码: <pre name="code"

HDU 3572 【最大流 &amp;&amp; 时间区间建图】

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5398    Accepted Submission(s): 1742 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

bzoj1061 建图 + 最小费用流

https://www.lydsy.com/JudgeOnline/problem.php?id=106152 对于一个点对上多个点,不太容易建图的时候,考虑逆向思考 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i 天至少需要 Ai 个人. 布布通过了解得知,一共有M 类志愿者可以招募.其中第i 类可以从第Si 天工作到第Ti 天,招募费用 是每人Ci

HDU 4067 Random Maze 费用流

Random Maze Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1114    Accepted Submission(s): 387 Problem Description In the game "A Chinese Ghost Story", there are many random mazes which h

hdu 4825 Xor Sum(trie+贪心)

hdu 4825 Xor Sum(trie+贪心) 刚刚补了前天的CF的D题再做这题感觉轻松了许多.简直一个模子啊...跑树上异或x最大值.贪心地让某位的值与x对应位的值不同即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #define CLR(a,b) memset((a)

Saving Princess claire_(hdu 4308 bfs模板题)

http://acm.hdu.edu.cn/showproblem.php?pid=4308 Saving Princess claire_ Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2305    Accepted Submission(s): 822 Problem Description Princess claire_ wa

hdu 4882 ZCC Loves Codefires (贪心 推导)

题目链接 做题的时候凑的规律,其实可以 用式子推一下的. 题意:n对数,每对数有e,k, 按照题目的要求(可以看下面的Hint就明白了)求最小的值. 分析:假设现在总的是sum, 有两个e1 k1 e2 k2 则先选e1 为 (sum+e1)*k1+(sum+e1+e2)*k2 先e2: (sum+e2)*k2 + (sum+e1+e2)*k1. 比较两个式子发现不同的部分分别是 e1*k2   e2*k1; 比较大小移向 e1/k1  e2/k2, 那个小,就选那个,能达到最小. 官方题解: