hdu3251 最小割

题意:

给n个城市,m条有向边。每条边有权值,如今有些城市能够选择得到。可选的城市有一个价值。可是要满足从1到达不了这些城市,为了满足要求能够去掉一些边,须要花费边的权值,问终于得到的最大价值是多少,并给出方案。

最小割 = 最大流

建图非常easy。源点就是1,设置汇点T。

按图中的有向边关系连边。

对于全部的可选择的城市u,连一条u->T的容量为w的边。

跑一遍最大流。即为最小割。

ans = sum - 最小割。

写出方案。就是走一遍bfs。看 哪些满流边(而且边的汇不是T,这是由于这种边是所选的城市扩展的边),打出来就好。

代码:

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
const int N = 1000 + 10 ;
const int inf = 1000000000;
typedef long long ll;
struct Edge
{
    int from,to,cap,flow;
};
int n,m,s,t,num,f;
int w[N],use[N];
int vis[2*N],cur[2*N];
vector<int> G[2*N];
vector<Edge> edges;
queue<int> cut;
void init()
{
    edges.clear();
    for(int i=1;i<=n;i++) G[i].clear();
    memset(vis,0,sizeof(vis));
}
int add(int u,int v,int c)
{
    edges.push_back((Edge){u,v,c,0});
    edges.push_back((Edge){v,u,0,0});
    num = edges.size();
    G[u].push_back(num-2);
    G[v].push_back(num-1);
}
int bfs()
{
    int front;
    memset(vis,0,sizeof(vis));
    vis[s] = 1;
    queue<int> q;
    q.push(s);
    while(!q.empty()){
        front = q.front(); q.pop();
        for(int i=0;i<G[front].size();i++)
        {
            Edge& e = edges[G[front][i]];
            if(!vis[e.to] && e.cap > e.flow)
            {
                q.push(e.to);
                vis[e.to] = vis[front]+1;
            }
        }
    }
    return vis[t];
}
int dfs(int x,int a)
{
    if(x==t || a==0) return a;
    int f=0,flow=0;
    for(int i=0;i<G[x].size();i++){
        Edge& e = edges[G[x][i]];
        if(vis[e.to]==vis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0 )
        {
            flow += f;
            e.flow += f;
            a -= f;
            edges[G[x][i]^1].flow -= f;
            if(a==0) break;
        }
    }
    return flow;
}
int dinic()
{
    int flow = 0;
    while(bfs())
    {
        memset(cur,0,sizeof(cur));
        flow += dfs(s,inf);
    }
    return flow;
}
void find_cut()
{
    while(!cut.empty()) cut.pop();
    memset(vis,0,sizeof(vis));
    vis[1] = 1;
    queue<int> q;
    q.push(1);
    int front;
    while(!q.empty()){
        front = q.front(); q.pop();
        for(int i=0;i<G[front].size();i++){
            Edge& e = edges[G[front][i]];
            if(!vis[e.to] && e.cap > e.flow){
                vis[e.to] = 1;
                q.push(e.to);
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(vis[i])
            for(int j=0;j<G[i].size();j++){
                Edge& e = edges[G[i][j]];
                if(G[i][j]&1) continue;
                if(e.to!=t  && !vis[e.to])
                    cut.push(G[i][j]/2+1);
            }
    }
    return ;
}
void print_cut()
{
    int len = cut.size();
    int ro;
    cout<<len<<" ";
    for(int i=1;i<len;i++){
        ro = cut.front();
        cut.pop();
        printf("%d ",ro);
    }
    ro = cut.front();
    cut.pop();
    printf("%d\n",ro);
}
int main()
{
    int T,cas=0;
    scanf("%d",&T);
    while(T--){
        ll sum = 0;
        scanf("%d%d%d",&n,&m,&f);
        init();
        s = 1; t = n+1;
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
        }
        for(int i=1;i<=f;i++){
            int u,w;
            scanf("%d%d",&u,&w);
            add(u,t,w);
            sum += w;
        }
        ll ans = dinic();
        find_cut();
        printf("Case %d: %lld\n",++cas,sum-ans);
        print_cut();
    }
    return 0;
}
时间: 2024-08-03 23:23:40

hdu3251 最小割的相关文章

【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得

hdoj 4289 Control 【拆点 求最小割】

Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2295    Accepted Submission(s): 961 Problem Description You, the head of Department of Security, recently received a top-secret informati

There is a war (hdu 2435 最小割+枚举)

There is a war Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 970    Accepted Submission(s): 277 Problem Description There is a sea. There are N islands in the sea. There are some directional

HDU 3657 Game(取数 最小割)经典

Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1065    Accepted Submission(s): 449 Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each g

POJ2914 Minimum Cut【全局最小割】【Stoer-Wangner】

题目链接: http://poj.org/problem?id=2914 题目大意: 提一个无向有重边的图,有重边的边权累加起来,求全局最小割. 思路: 一个无向连通图,去掉一个边集可以使其变成两个连通分量则这个边集就是割集.最小割 集当然就是权和最小的割集. 这是一个最简单的全局最小割模板题.直接套上模板就可以了.来说说Stoer-Wangner算 法吧. Stoer-Wangner算法: 对于图中的任意两个顶点u和v,若u,v属于最小割的同一个集合中,那么僵顶点u和顶点 v合并后并不影响图的

HDU 3035 War(对偶图求最小割)

HDU 3035 War 题目链接 题意:根据图那样,给定一个网络,要求阻断s到t,需要炸边的最小代价 思路:显然的最小割,但是也显然的直接建图强行网络流会超时,这题要利用平面图求最小割的方法,把每一块当成一个点,共有边连边,然后每一个路径就是一个割,然后最短路就是最小割了 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace s

ZOJ 2587 Unique Attack 判断最小割是否唯一

很裸的判断最小割是否唯一.判断方法是先做一遍最大流求最小割,然后从源点和汇点分别遍历所有能够到达的点,看是否覆盖了所有的点,如果覆盖了所有的点,那就是唯一的,否则就是不唯一的. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostr

AHOI2009最小割

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1072  Solved: 446[Submit][Status] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案,使中转站s不能到

bzoj1412-网络流最小割

狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆.可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已.所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养. 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变