SGU 242 Student's Morning 网络流(水

题目链接:点击打开链接

题意:

给定n个人,m个终点

下面n行表示每个人可以去m个点。

每个人只能去一个点。

输出任意一个方案使得每个点至少有2个人到达。

若存在输出m行,第一个数字表示i这个点来了几个人,后面是人的点标。

思路:

建一个二部图n-m,然后m到汇点限流2,判断是否满流,若不满流就无解。

若满流则其他的人随便走。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <queue>
#include <set>
#include <algorithm>
using namespace std;
typedef int ll;
#define N 420
#define M 100000
#define inf 107374182
struct Edge{
    ll from, to, cap, nex;
}edge[M*2];
ll head[N], edgenum;
void add(ll u, ll v, ll cap, ll rw = 0){
    Edge E = {u, v, cap, head[u]};
    edge[edgenum] = E;
    head[u] = edgenum ++;
    Edge E2 = {v, u, rw, head[v]};
    edge[edgenum] = E2;
    head[v] = edgenum ++;
}
ll sign[N];
bool BFS(ll from, ll to){
    memset(sign, -1, sizeof sign);
    sign[from] = 0;
    queue<ll>q;
    q.push(from);
    while( !q.empty() ) {
        ll u = q.front(); q.pop();
        for(ll i = head[u]; ~i; i = edge[i].nex)
        {
            ll v = edge[i].to;
            if(sign[v] == -1 && edge[i].cap){
                sign[v] = sign[u] +1, q.push(v);
                if(sign[to] != -1) return true;
            }
        }
    }
    return false;
}
ll Stack[N], top, cur[N];
ll Dinic(ll from, ll to){
    ll ans = 0;
    while( BFS(from, to) )
    {
        memcpy(cur, head, sizeof head);
        ll u = from; top = 0;
        while(1)
        {
            if(u==to)
            {
                ll flow = inf, loc;
                for(ll i = 0; i < top; i++)
                    if(flow > edge[Stack[i]].cap)
                    {
                        flow = edge[Stack[i]].cap;
                        loc = i;
                    }
                for(ll i = 0; i < top; i++)
                {
                    edge[ Stack[i] ].cap -= flow;
                    edge[Stack[i]^1].cap += flow;
                }
                ans += flow;
                top = loc;
                u = edge[Stack[top]].from;
            }
            for(ll i = cur[u]; ~i; cur[u] = i = edge[i].nex)
                if(edge[i].cap && (sign[u]+1 == sign[edge[i].to]))break;
            if(cur[u] != -1){
                Stack[top++] = cur[u];
                u = edge[cur[u]].to;
            }
            else
            {
                if(top==0)break;
                sign[u] = -1;
                u = edge[Stack[--top]].from;
            }
        }
    }
    return ans;
}
void init(){memset(head, -1, sizeof head); edgenum = 0;}
int n, m, from, to, to2, ans[N], G[N];
vector<int>D[N];
bool solve(){
    from = 0; to = n+m+1; to2 = to+1;
    init();
    for(int i = 1; i <= n; i++)
    {
        G[i] = -1;
        add(from, i, 1);
        int x, y; scanf("%d",&x);
        while(x--){
            scanf("%d",&y);
            G[i] = y;
            add(i, n+y, 1);
        }
    }
    for(int i = 1; i <= m; i++)
        add(n+i, to, 2);
    add(to, to2, inf);
    if(m*2 > n || Dinic(from, to2) < m*2)return false;
    puts("YES");
    for(int i = 1; i <= n; i++)
    {
        ans[i] = -1;
        for(int j = head[i]; ~j; j = edge[j].nex)
        {
            if(edge[j].cap==0 && edge[j].to != from)
            {
                ans[i] = edge[j].to-n;
                D[edge[j].to-n].push_back(i);
                break;
            }
        }
        if(ans[i]==-1 && G[i]!=-1)
            D[G[i]].push_back(i);
    }
    for(int i = 1; i <= m; i++)
    {
        printf("%d", D[i].size());
        for(int j = 0; j < D[i].size(); j++)
            printf(" %d", D[i][j]);
        puts("");
    }
    return true;
}
int main(){
	while(~scanf("%d %d",&n,&m)){
        if(solve()==false)puts("NO");
        for(int i = 1; i <= m; i++)D[i].clear();
	}
	return 0;
}
/*
5 2
1 1
1 2
1 1
1 1
1 1

5 2
1 1
1 2
1 1
1 1
2 1 2

*/

SGU 242 Student's Morning 网络流(水

时间: 2024-10-03 00:57:29

SGU 242 Student's Morning 网络流(水的相关文章

SGU 242. Student&#39;s Morning( 网络流 )

看英文题真是麻烦...理解题意花的时间比想的时间还长...裸的网络流, 我们只要限制每个人出发流量为1, 每个大学进入的流量至多为2即可, 相当于构造可行解. ---------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<cctype&

SGU 242 Student&amp;#39;s Morning 网络流(水

题目链接:contest=0&problem=242">点击打开链接 题意: 给定n个人,m个终点 以下n行表示每一个人能够去m个点. 每一个人仅仅能去一个点. 输出随意一个方案使得每一个点至少有2个人到达. 若存在输出m行,第一个数字表示i这个点来了几个人,后面是人的点标. 思路: 建一个二部图n-m,然后m到汇点限流2.推断是否满流,若不满流就无解. 若满流则其它的人随便走. #include <stdio.h> #include <string.h>

Coprimes - SGU 102(求互质数,水)

题目大意:给你一个正整数N,求出来不超过N 的并且与N互质的正整数的个数. 就是一个大水题~~~ 代码: #include<stdio.h> #include<string.h> int GCD(int m, int n) { if(n == 0) return m; return GCD(n, m%n); } int main() { int N, sum=0; scanf("%d", &N); for(int i=1; i<=N; i++) {

网络流专栏

最大流 POJ 1273 Drainage Ditches POJ 1274 The Perfect Stall (二分图匹配) POJ 1698 Alice's Chance(构图) POJ 1459 Power Network(构图) POJ 2112 Optimal Milking (二分) POJ 2455 Secret Milking Machine (二分) POJ 3189 Steady Cow Assignment (枚举) POJ 1637 Sightseeing tour (

网络流柱

最大流量 POJ 1273 Drainage Ditches POJ 1274 The Perfect Stall (二分图匹配) POJ 1698 Alice's Chance(构图) POJ 1459 Power Network(构图) POJ 2112 Optimal Milking (二分) POJ 2455 Secret Milking Machine (二分) POJ 3189 Steady Cow Assignment (枚举) POJ 1637 Sightseeing tour

网络流题集

最大流POJ 1273 Drainage DitchesPOJ 1274 The Perfect Stall (二分图匹配)POJ 1698 Alice's Chance(构图)POJ 1459 Power Network(构图)POJ 2112 Optimal Milking (二分)POJ 2455 Secret Milking Machine (二分)POJ 3189 Steady Cow Assignment (枚举)POJ 1637 Sightseeing tour (混合图欧拉回路)

Soj题目分类

-----------------------------最优化问题------------------------------------- ----------------------常规动态规划  SOJ1162 I-Keyboard  SOJ1685 Chopsticks SOJ1679 Gangsters SOJ2096 Maximum Submatrix  SOJ2111 littleken bg SOJ2142 Cow Exhibition  SOJ2505 The County

待刷题目分类

各大OJ题目归类 Posted on 2012 年 8 月 8 日 by admin ---------–最优化问题------------- --------动态规划 SOJ1162 I-Keyboard SOJ2096 Maximum Submatrix SOJ2111 littleken bg SOJ2505 The County Fair SOJ2818 QQ音速 SOJ2469 Exploring Pyramids SOJ1833 Base Numbers SOJ2009 Zeros

Lambda(Linq)

在谈到lambda表达式之前,首先要说一下委托,在下一章会详细介绍委托,在这里就是简单说明一下. 委托的关键字段delegate,声明委托 public delegate void NoReturnNoPara();//1 委托的声明 public delegate int WithReturnNoPara(); public delegate void NoReturnWithPara(int id, string name); public delegate LambdaShow WithR