MZL's City(网络流)

MZL‘s City

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 496    Accepted Submission(s): 164

Problem Description

MZL is an active girl who has her own country.

Her big country has N cities numbered from 1 to N.She has controled the country for so long and she only remebered that there was a big earthquake M years ago,which made all the roads between the cities destroyed and all the city became broken.She also remebered
that exactly one of the following things happened every recent M years:

1.She rebuild some cities that are connected with X directly and indirectly.Notice that if a city was rebuilt that it will never be broken again.

2.There is a bidirectional road between city X and city Y built.

3.There is a earthquake happened and some roads were destroyed.

She forgot the exactly cities that were rebuilt,but she only knew that no more than K cities were rebuilt in one year.Now she only want to know the maximal number of cities that could be rebuilt.At the same time she want you to tell her the smallest lexicographically
plan under the best answer.Notice that 8 2 1 is smaller than 10 0 1.

Input

The first contains one integer T(T<=50),indicating the number of tests.

For each test,the first line contains three integers N,M,K(N<=200,M<=500,K<=200),indicating the number of MZL’s country ,the years happened a big earthquake and the limit of the rebuild.Next M lines,each line contains a operation,and the format is “1 x” , “2
x y”,or a operation of type 3.

If it’s type 3,first it is a interger p,indicating the number of the destoyed roads,next 2*p numbers,describing the p destoyed roads as (x,y).It’s guaranteed in any time there is no more than 1 road between every two cities and the road destoyed must exist
in that time.

Output

The First line Ans is the maximal number of the city rebuilt,the second line is a array of length of tot describing the plan you give(tot is the number of the operation of type 1).

Sample Input

1
5 6 2
2 1 2
2 1 3
1 1
1 2
3 1 1 2
1 2

Sample Output

3
0 2 1

Hint

 No city was rebuilt in the third year,city 1 and city 3 were rebuilt in the fourth year,and city 2 was rebuilt in the sixth year.

题意:
                  一个国家原本有n个城市和若干条联通城市的路,可是在M年前,因为一场大地震,整个国家都被摧毁了.
           现在打算在m年里,重建国家,有三个操作:
          1.> 输入1,x,表示可以修建包含x在内的间接或者直接相连的城市.
          2.> 输入2,x,y表示新建x到y的无向边
          3.> 输入3,p,表示要摧毁p条道路,接下来输入2p个数,分别表示p条路;
          最后问最终能够修建多少个城市.和输出一个字典序最小的方案;

题解:
         网络流可以做;
         把年份分为一边,城市分为另一边,连边构图;
         从s往所有年份连一条容量为k的边,所有城市往汇点t连一条容量为1的边;
        其他的点,按照关系连一条容量为1的边;
        因为题目要求以最小字典序输出,所以我们从后往前做网络流;

AC代码:
/* ***********************************************
Author        :xdlove
Created Time  :2015年07月31日 星期五 12时37分29秒
File Name     :a.cpp
 ************************************************ */

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

/**宏定义类
 * **/
#define FOR(i,s,t) for(int i = (s); i < (t); i++)
#define FOR_REV(i,s,t) for(int i = (s - 1); i >= (t); i--)
#define mid ((l + r) >> 1)
#define clr(a) memset(a,0,sizeof(a))
#define lson l,mid,u<<1
#define rson mid+1,r,u<<1|1
#define ls u<<1
#define rs u<<1|1

typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double pi = acos(-1.0);

/**输入输出挂类模板
 * **/

class Fast
{
    public:
        inline void rd(int &ret)
        {
            char c;
            int sgn;
            if(c = getchar(),c == EOF) return;
            while(c != '-' && (c < '0' || c > '9')) c = getchar();
            sgn = (c == '-') ? -1 : 1;
            ret = (c == '-') ? 0 : (c - '0');
            while(c = getchar(),c >= '0' && c <= '9')
                ret = ret * 10 + c - '0';
            ret *= sgn;
        }

    public:
        inline void pt(int x)
        {
            if(x < 0)
            {
                putchar('-');
                x = -x;
            }
            if(x > 9) pt(x / 10);
            putchar(x % 10 + '0');
        }
};
Fast xd;

const int MAXM = 1e6;
const int MAXN = 1000;

struct Node
{
    int from,to,next;
    int cap;
}edge[MAXM * 2];
int tol;
int Head[MAXN];
int que[MAXN];
int dep[MAXN]; //dep为点的层次
int stack[MAXN];//stack为栈,存储当前增广路
int cur[MAXN],cnt;//存储当前点的后继

void Init()
{
    tol = cnt = 0;
    memset(Head,-1,sizeof(Head));
}

void add_edge(int u, int v, int w)
{
    //printf("%d: %d: %d\n",u,v,w);
    edge[tol].from = u;
    edge[tol].to = v;
    edge[tol].cap = w;
    edge[tol].next = Head[u];
    Head[u] = tol++;
    edge[tol].from = v;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].next = Head[v];
    Head[v] = tol++;
}

int BFS(int start, int end)
{
    int front, rear;
    front = rear = 0;
    memset(dep, -1, sizeof(dep));
    que[rear++] = start;
    dep[start] = 0;
    while (front != rear)
    {
        int u = que[front++];
        if (front == MAXN)front = 0;
        for (int i = Head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (edge[i].cap > 0 && dep[v] == -1)
            {
                dep[v] = dep[u] + 1;
                que[rear++] = v;
                if (rear >= MAXN)rear = 0;
                if (v == end)return 1;
            }
        }
    }
    return 0;
}

int dinic(int start, int end)
{
    int res = 0;
    int top;
    while (BFS(start, end))
    {
        memcpy(cur, Head, sizeof(Head));
        int u = start;
        top = 0;
        while (true)
        {
            if (u == end)
            {
                int min = INF;
                int loc;
                for (int i = 0; i < top; i++)
                    if (min > edge[stack[i]].cap)
                    {
                        min = edge[stack[i]].cap;
                        loc = i;
                    }
                for (int i = 0; i < top; i++)
                {
                    edge[stack[i]].cap -= min;
                    edge[stack[i] ^ 1].cap += min;
                }
                res += min;
                top = loc;
                u = edge[stack[top]].from;
            }
            for (int i = cur[u]; i != -1; cur[u] = i = edge[i].next)
                if (edge[i].cap != 0 && dep[u] + 1 == dep[edge[i].to])
                    break;
            if (cur[u] != -1)
            {
                stack[top++] = cur[u];
                u = edge[cur[u]].to;
            }
            else
            {
                if (top == 0)break;
                dep[u] = -1;
                u = edge[stack[--top]].from;
            }
        }
    }
    return res;
}

int g[205][205],used[205];
int Stack[600];
int n,m,k;

void dfs(int u)
{
    used[u] = 1;
    add_edge(cnt,u + m,1);
    FOR(v, 1, 1 + n)
    {
        if(g[u][v] && !used[v])
        {
            used[v] = 1;
            dfs(v);
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;
    xd.rd(T);
    while(T--)
    {
        Init();
        xd.rd(n);
        xd.rd(m);
        xd.rd(k);
        clr(g);
        clr(used);
        vector<int> p;
        FOR(i, 0, m)
        {
            int o,x,y;
            xd.rd(o);
            if(o == 2)
            {
                xd.rd(x);
                xd.rd(y);
                g[x][y] = g[y][x] = 1;
            }
            else if(o == 3)
            {
                xd.rd(o);
                FOR(i, 0, o)
                {
                    xd.rd(x);
                    xd.rd(y);
                    g[x][y] = g[y][x] = 0;
                }
            }
            else
            {
                cnt++;
                clr(used);
                p.push_back(cnt);
                xd.rd(x);
                dfs(x);
            }
        }
        int s = 0,t = n + m + 1;
        for(int i = 1; i <= n; i++)
            add_edge(i + m,t,1);
        int pos = 0,sum = 0;
        for(vector<int> :: iterator it = --p.end(); ; it--)
        {
            int id = *it;
            //cout<<id<<endl;
            add_edge(s,id,k);
            Stack[pos++] = dinic(s,t);
            sum += Stack[pos - 1];
            if(it == p.begin()) break;
        }
        printf("%d\n",sum);
        FOR_REV(i,pos,0)
        {
            if(i != pos - 1) putchar(' ');
            printf("%d",Stack[i]);
        }
        puts("");
    }
    return 0;
}

版权声明:追逐心中的梦想,永不放弃! By-xdlove

MZL's City(网络流)

时间: 2024-10-12 03:30:25

MZL's City(网络流)的相关文章

Hdu 5352 MZL&#39;s City (多重匹配)

题目链接: Hdu 5352 MZL's City 题目描述: 有n各节点,m个操作.刚开始的时候节点都是相互独立的,一共有三种操作: 1:把所有和x在一个连通块内的未重建过的点全部重建. 2:建立一条双向路(x,y) 3:又发生了地震,p条路被毁. 问最后最多有多少个节点被重建,输出重建节点的最小字典序. 解题思路: 这几天正好在学匹配,但是昨天下午还是没有看出来这个是匹配题目.看了题解扪心自问了自己三次,是不是傻.就是把每个需要重建的节点x拆成k个点,然后对每个拆分后的点和与拆点在同一连通块

hdu 5352 MZL&#39;s City 最小费用最大流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5352 题意:M年前有一个国家发生了地震.所有城市和城市之间的路都被摧毁了.现在要重建城市. 给出一个N表示共有N个城市,M表示大地震发生在M年前,K表示每次最多只能重建K个城市. 现在从大地震发生的那年开始,每年可以进行一个操作,也就是总共有M个操作. 1 x表示可以重建和x联通(直接或间接)的城市(包括x本身),每次最多只能重建K个城市 2 x y 表示修建了一条城市x到城市y的路. 3操作给出一

hdu5352 MZL&#39;s City(最小费用最大流问题)

题意描述: 一个国家有N个城市,标号1~N,初始时城市和道路都被破坏,下面进行以下三个操作: 第一种操作:1 X 修建城市,和X(包括X自己也可以被修建)直接相连或间接相连的城市可以被一次性修建(但一次性最多修建k个城市) 第二种操作:2 X Y 在X 与 Y之间建立一条道路 第三种操作:3 p X1 Y1 X2 Y2 ··· 表示破坏X1与Y1.X2与Y2之间的道路 经过M次操作后,对于这M次操作中的操作一,我们在每次操作一时修建多少城市修建那些城市才能使最终城市数量最多? 并输出最终修建城市

HDOJ 5352 MZL&#39;s City 匈牙利匹配

求年份和城市的匹配 MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 539    Accepted Submission(s): 180 Problem Description MZL is an active girl who has her own country. Her big country has N

hdu 5352 MZL&#39;s City 【二分图】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5352 题意: 给你n,m,k 表示n个建筑 m次操作,修复操作每次最多修复k个建筑. 有三种操作 1.修复x点周围建筑(<=k) 2.x,y建筑间建边 3.x,y间删边 修复建筑时候拆点建图.反着求最大匹配,保证字典序最小. 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <l

HDU 5352 MZL&#39;s City

最小费用最大流,因为要控制字典序,网络流控制不好了...一直WA,所以用了费用流,时间早的费用大,时间晚的费用少. 构图: 建立一个超级源点和超级汇点.超级源点连向1操作,容量为K,费用为COST,然后COST-1,因为下一次遇到1操作,费用为减少1,即COST-1: 每个1操作连向当前能建造的城市,容量为1,费用为0: 每个城市连向汇点,容量为1,费用为0: #include<cstdio> #include<cstring> #include<cmath> #inc

HDU 5352——MZL&#39;s City——————【二分图多重匹配、拆点】

MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 710    Accepted Submission(s): 245 Problem Description MZL is an active girl who has her own country. Her big country has N cities numb

MZL&#39;s City (hdu 5352 最小费用流 ||二分图匹配)

MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 719    Accepted Submission(s): 251 Problem Description MZL is an active girl who has her own country. Her big country has N cities num

HDU 5352 MZL&#39;s City(2015 多校 第5场,最小费用最大流)

  MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 291    Accepted Submission(s): 94 Problem Description MZL is an active girl who has her own country. Her big country has N cities nu