hust 1342 - Cheat Secretly(有源汇有上下界的最小流)

1342 - Cheat Secretly

Time Limit: 1s Memory Limit: 128MB

Submissions: 430 Solved: 143
DESCRIPTION
HH Big Cow(HBC) has taken part in an interesting treasure finding match. In the match there are N transmitting nodes(labeled from 1 to N), and between these nodes there are M directional roads. In the middle of some roads there may be a “gift-spot”, where a beautiful girl gives a gift to the contestant who passes that road. The one who gets most gifts wins! Winning the match is so easy for HBC, so he is thinking of a more challenging thing —— collecting gifts from ALL the girls. HBC has an amazing ability to achieve this goal: When he comes to a dead end, he can transfer himself to another node arbitrarily. With that ability, of course he can achieve the goal of meeting all the girls, however, cheating is not good! So he decides to use the ability as few as possible. Now he wants to know the fewest times he should use that ability to achieve his goal. NOTE: 1. The graph in the match is a directed acyclic graph (DAG). 2. There is at most one road between any two nodes.
INPUT
The input contains multiple case. Line 1 an integer T : number of test cases. Line 2 two integer N, M: N for number of nodes. (2 <= N <= 500) M for number of roads. (1 <= M <= 10000) Lines 3..M+2 each line three integers a, b, c: representing a directed roads from a to b. (1 <= a, b <= N) c = 1, then there is a gift spot on this road. c = 0, then there is no gift spot on this road.
OUTPUT
For each case output one line representing the fewest number of ability HBC should use.
SAMPLE INPUT
2

4 2

1 2 1
3 4 1

6 7

1 2 1
2 3 1
3 4 1
1 4 0
5 2 1
3 6 1
5 6 0
SAMPLE OUTPUT
Case #1: 2
Case #2: 2

最少能用几次走完必要边

n个节点 m条边 每条边给出3个值 u v w 分别代表边的起点终点 是否为必要边

建图比较简单 看代码可以理解

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>

#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 10010
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)

using namespace std;

void read(int &x)
{
    char ch;
    x=0;
    while(ch=getchar(),ch!=' '&&ch!='\n')
    {
        x=x*10+ch-'0';
    }
}

struct Edge
{
    int from,to,cap,flow;
    bool operator <(const Edge e) const
    {
        if(e.from!=from)  return from<e.from;
        else return to<e.to;
    }
    Edge() {}
    Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow) {}
};

struct Dinic
{
    vector<Edge> edges;
    vector<int> G[MAXN];
    bool vis[MAXN];//BFS使用
    int d[MAXN];   //从起点到i的距离
    int cur[MAXN]; //当前弧下标
    int n,m,s,t,maxflow;   //节点数 边数(包括反向弧) 源点编号和弧点编号

    void init(int n)
    {
        this->n=n;
        for(int i=0;i<=n;i++)
            G[i].clear();
        edges.clear();
    }

    void addedge(int from,int to,int cap)
    {
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool bfs()
    {
        MEM(vis,0);
        MEM(d,-1);
        queue<int> q;
        q.push(s);
        d[s]=maxflow=0;
        vis[s]=1;
        while(!q.empty())
        {
            int u=q.front(); q.pop();
            int sz=G[u].size();
            for(int i=0;i<sz;i++)
            {
                Edge e=edges[G[u][i]];
                if(!vis[e.to]&&e.cap>e.flow)
                {
                    d[e.to]=d[u]+1;
                    vis[e.to]=1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int dfs(int u,int a)
    {
        if(u==t||a==0)  return a;
        int sz=G[u].size();
        int flow=0,f;
        for(int &i=cur[u];i<sz;i++)
        {
            Edge &e=edges[G[u][i]];
            if(d[u]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
            {
                e.flow+=f;
                edges[G[u][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0)  break;
            }
        }
        return flow;
    }

    int Maxflow(int s,int t)
    {
        this->s=s; this->t=t;
        int flow=0;
        while(bfs())
        {
            MEM(cur,0);
            flow+=dfs(s,INF);
        }
        return flow;
    }
}Dic;

int low[550];

int main()
{
//    fread;
    int tc;
    scanf("%d",&tc);
    int cs=1;
    while(tc--)
    {
        MEM(low,0);
        int n,m;
        scanf("%d%d",&n,&m);
        int s=0,t=n+1;
        int ss=n+2,tt=n+3;
        Dic.init(tt);
        for(int i=1;i<=n;i++)
        {
            Dic.addedge(s,i,INF);
            Dic.addedge(i,t,INF);
        }
        while(m--)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(w)
            {
                low[u]--; low[v]++;
            }
            Dic.addedge(u,v,INF);
        }
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            if(low[i]>0)
            {
                sum+=low[i];
                Dic.addedge(ss,i,low[i]);
            }
            else
                Dic.addedge(i,tt,-low[i]);
        }
        int mx=Dic.Maxflow(ss,tt);
        Dic.addedge(t,s,INF);
        int id=Dic.edges.size()-2;
        mx=Dic.Maxflow(ss,tt);
        printf("Case #%d: %d\n",cs++,Dic.edges[id].flow);
    }
    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值