[HAOI2017]新型城市化

题目描述

Anihc国有n座城市.城市之间存在若一些贸易合作关系.如果城市x与城市y之间存在贸易协定.那么城市文和城市y则是一对贸易伙伴(注意:(x,y)和(y,x))是同一对城市)。

为了实现新型城市化.实现统筹城乡一体化以及发挥城市群辐射与带动作用.国 决定规划新型城市关系。一些城市能够被称为城市群的条件是:这些城市两两都是贸易伙伴。 由于Anihc国之前也一直很重视城市关系建设.所以可以保证在目前已存在的贸易合作关系的情况下Anihc的n座城市可以恰好被划分为不超过两个城市群。

为了建设新型城市关系Anihc国想要选出两个之前并不是贸易伙伴的城市.使这两个城市成为贸易伙伴.并且要求在这两个城市成为贸易伙伴之后.最大城市群的大小至少比他们成为贸易伙伴之前的最大城市群的大小增加1。

Anihc国需要在下一次会议上讨论扩大建设新型城市关系的问题.所以要请你求出在哪些城市之间建立贸易伙伴关系可以使得这个条件成立.即建立此关系前后的最大城市群的 大小至少相差1。

输入输出格式

输入格式:

第一行2个整数n,m.表示城市的个数,目前还没有建立贸易伙伴关系的城市的对数。

接下来m行,每行2个整数x,y表示城市x,y之间目前还没有建立贸易伙伴关系。

输出格式:

第一行yi个整数ans,表示符合条件的城市的对数.注意(x,y)与(y,x)算同一对城市。

接下来Ans行,每行两个整数,表示一对可以选择来建立贸易伙伴关系的城市。对于 一对城市x,y请先输出编号更小的那一个。最后城市对与城市对之间顺序请按照字典序从小到大输出。

输入输出样例

输入样例#1:

5 3
1 5
2 4
2 5

输出样例#1:

2
1 5
2 4

说明

数据规模与约定

数据点1: n≤16

数据点2: n≤16

数据点3~5: n≤100

数据点6: n≤500

数据点7~10: n≤10000

对于所有的数据保证:n <= 10000,0 <= m <= min (150000,n(n-1)/2).保证输入的城市关系中不会出现(x,x)这样的关系.同一对城市也不会出现两次(无重边.无自环)。

Solution

单纯想练习码力的可以看一句话题意解释,一个二分图,求删去那些边可以是二分图的最大独立集的大小+1.

BZOJ暂时没有这个题。。以为网络流的骚操作也弄得差不多了,然而还是自己太naive了。

看看这个题目,首先给出的样例和输入方式特别像,一个图。。。所以我们就把这些边都连起来。。然后我们根据题意可以发现,如果一堆城市属于一个城市群,那么这些城市之间彼此都不会连边。那么按照我刚才的连边方法,就出来一个二分图。那么最大的城市群就是最大的的独立集,建立关系就是删去图中的一条边,那么因为:最大独立集=总点数-最小覆盖集 可以得出我们要求的就是删去图中的那些边可以使这个图的最大匹配增加1。

那么这个题就比较显而易见了,可以先跑一遍网络流,然后再一遍枚举一边一遍一遍的跑网络流。。。不过这题数据范围最多也就过到5个点吧。然后根据定理:若一条边一定在最大匹配中,则在最终的残量网络中,这条边一定满流,且这条边的两个顶点一定不在同一个强连通分量中。 可以跑Tarjan搞一搞,然后暴力枚举边来判断就行。证明网上搜搜应该能有,这里不给出了。‘

Code

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <set>
#include <map>
#define MAXN 200000
#define re register
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(arr) memset(arr, 0, sizeof(arr))
const int inf = 0x3f3f3f3f;
struct po
{
    int nxt,to,w,from;
}edge[250001];
struct ANS
{
    int x,y;
}ans[MAXN];
int n,m,cur[MAXN],head[20002],num=-1,dep[20002],s,t,c[MAXN],vis[20002];
inline int read()
{
    int x=0,c=1;
    char ch=' ';
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    while(ch=='-') c*=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
inline void add_edge(int from,int to,int w)
{
    edge[++num].nxt=head[from];
    edge[num].from=from;
    edge[num].to=to;
    edge[num].w=w;
    head[from]=num;
}
inline void add(int from,int to,int w)
{
    add_edge(from,to,w);
    add_edge(to,from,0);
}
inline bool bfs()
{
    memset(dep,0,sizeof(dep));
    queue<int> q;
    while(!q.empty())
    q.pop();
    q.push(s);
    dep[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(re int i=head[u];i!=-1;i=edge[i].nxt)
        {
            int v=edge[i].to;
            if(dep[v]==0&&edge[i].w>0)
            {
                dep[v]=dep[u]+1;
                if(v==t)
                return 1;
                q.push(v);
            }
        }
    }
    return 0;
}
inline int dfs(int u,int dis)
{
    if(u==t)
    return dis;
    int diss=0;
    for(re int& i=cur[u];i!=-1;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(edge[i].w!=0&&dep[v]==dep[u]+1)
        {
            int check=dfs(v,min(dis,edge[i].w));
            if(check!=0)
            {
                dis-=check;
                diss+=check;
                edge[i].w-=check;
                edge[i^1].w+=check;
                if(dis==0) break;
            }
        }
    }
    return diss;
}
inline void dinic()
{
    while(bfs())
    {
        for(re int i=s;i<=t;i++)
        cur[i]=head[i];
        while(int d=dfs(s,inf));
    }
}
void put_color(int u,int col)
{
    c[u]=col;
    vis[u]=1;
    for(re int i=head[u];i!=-1;i=edge[i].nxt){
        int v=edge[i].to;
        if(!vis[v]) put_color(v,col^1);
    }
}
int dfn[MAXN],low[MAXN],stack[MAXN],color_num,color[MAXN],cnt,top;
inline void Tarjan(int u)
{
    dfn[u]=low[u]=++cnt;
    vis[u]=1;
    stack[++top]=u;
    for(re int i=head[u];i!=-1;i=edge[i].nxt){
        if(!edge[i].w){
            int v=edge[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            } else if(vis[v]) low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        color[u]=++color_num;
        vis[u]=0;
        while(stack[top]!=u){
            color[stack[top]]=color_num;
            vis[stack[top--]]=0;
        }
        top--;
    }
}
int x[MAXN],y[MAXN],tot;
inline bool cmp(ANS a,ANS b){
    return a.x==b.x?a.y<b.y:a.x<b.x;
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();m=read();
    for(re int i=1;i<=m;i++){
        x[i]=read();y[i]=read();
        add_edge(x[i],y[i],0);
        add_edge(y[i],x[i],1);
    }

    for(re int i=1;i<=n;i++)
        if(!vis[i]) put_color(i,2);
    memset(head,-1,sizeof(head));
    s=0,t=n+1;num=-1;
    for(re int i=1;i<=n;i++){
        if(c[i]==2)
            add(s,i,1);
        else add(i,t,1);
    }
    for(re int i=1;i<=m;i++){
        if(c[x[i]]==2)
            add(x[i],y[i],1);
        else add(y[i],x[i],1);
    }
    dinic();
    memset(vis,0,sizeof(0));
    for(re int i=1;i<=n;i++)
        if(!dfn[i]) Tarjan(i);
    for(re int i=0;i<=num;i+=2){
        int u=edge[i].from,v=edge[i].to;
        if(!edge[i].w&&color[u]!=color[v]&&u!=s&&v!=t&&u!=t&&v!=s){
            if(u>v) swap(u,v);
            ans[++tot].x=u;ans[tot].y=v;
        }
    }

    sort(ans+1,ans+tot+1,cmp);
    cout<<tot<<endl;
    for(re int i=1;i<=tot;i++)
        printf("%d %d\n", ans[i].x,ans[i].y);
    return 0;
}
/*6 5 3 7 2 4 1*/

原文地址:https://www.cnblogs.com/victorique/p/9026473.html

时间: 2024-10-14 00:10:11

[HAOI2017]新型城市化的相关文章

洛谷 P3731 [HAOI2017]新型城市化【最大流(二分图匹配)+tarjan】

我到底怎么建的图为啥要开这么大的数组啊?! 神题神题,本来以为图论出不出什么花来了. 首先要理解'团'的概念,简单来说就是无向图的一个完全子图,相关概念详见度娘. 所以关于团一般都是NP问题,只有二分图例外.而题目中有这样一句话"n座城市可以恰好被划分为不超过两个城市群",并且给出的是没有的边,也就是这个图的补图,两个团就很显然表示这个补图是个二分图(我一开始还考虑1个团咋整后来发现根本不用整= =),模型就变成了二分图的最大独立集,考虑最大独立集=n-最大匹配,那么只要求出删掉哪些边

Luogu3731 HAOI2017新型城市化(二分图匹配+强连通分量)

将未建立贸易关系看成连一条边,那么这显然是个二分图.最大城市群即最大独立集,也即n-最大匹配.现在要求的就是删哪些边会使最大匹配减少,也即求哪些边一定在最大匹配中. 首先范围有点大,当然是跑个dinic,转化成最大流.会使最大流减少的边相当于可能在最小割中的边,因为删掉它就相当于无代价的割掉了一条边.那么用曾经看到过的结论就可以了:当且仅当该边满流且残余网络(包括反向边)中该边两端点处于不同SCC时,该边可能在最小割中.不太会证.于是tarjan一发就可以了.注意不要把开始给的图和网络流建图搞混

[HAOI2017] 新型城市化 - 强联通分量,最大流,二分图染色

给定一个可以划分为不超过两个团的稠密图,以补图的形式描述.求有多少对点满足在它们之间建边后最大团的大小会增加.\(n \leq 10^4, m \leq 1.5\times 10^5\) Solution 原图的最大团就是补图的最大独立集,由题意补图是二分图,于是转化为求删去哪些边可以使得二分图的最大独立集减少 考虑到最大独立集数=最大匹配数,于是转化为求哪些边一定在最大匹配里 定理 二分图的某条边一定在最大匹配中当且仅当这条边满流,且残量网络中这条边的两个顶点不在同一个 SCC 中 于是我们跑

luogu3731 新型城市化

题目链接 思路 这道题对于题意的转化很关键. 题目要求的是添上一条边,使得图中最大团的大小变大.给出的边是原图的补集,这就给我们了提示. 因为题目中说,原图中最多有两个团.所以给出的边一定形成了一个二分图. 那么最大团就是新图中的最大独立集. 那么问题就转化成了,在新图中删除一条边,使得新图中的最大独立集变大. 因为最大独立集 = 点数-最大匹配. 所以我们要让最大匹配变小. 考虑删除哪些边会让最大匹配变小.首先肯定要在跑完网络流之后是满流的.然后不能由其他的边来代替.也就是说在残余网络上跑一遍

公交wifi运营平台分析

一.前言背景 昨晚下午,老板让看一些车载公交wifi后台管理的一些东西,这个随着移动端设备而兴起的wifi战,慢慢的也会越演越烈. 现在于很多人在外面的时候,进入一家店首先看的不是菜单,而是问一句“你们的wifi密码是多少”?没有贴着“免费wifi”标签的店,估计都不会有人进去用餐,咖啡店,甜品店,餐厅,美发店……到处都可以看到免费wifi的字样,wifi已经成为标配了.随着移动端的兴起,微信营销的推广,对WiFi的需求也越来越多,这个可以说是生有体会,武汉某商圈的兴起就和wifi,微信脱不了关

草根智库最新热点 - 土地流转:美元资本将敲响中国社会崩溃的丧钟 - QQ邮箱

body { font-family: 微软雅黑; font-size: 10.5pt; line-height: 1.5; } html, body { color: ; background-color: ; } h1 { font-size:1.5em; font-weight:bold; } h2 { font-size:1.4em; font-weight:bold; } h3 { font-size:1.3em; font-weight:bold; } h4 { font-size:

Python程序猿必知的新型字符串格式漏洞

本文对Python开发中引入的一种格式化字符串的新型语法的安全漏洞进行了深入的分析,并提供了相应的安全解决方案. 当我们对不可信的用户输入使用str.format的时候,将会带来安全隐患--对于这个问题,其实我早就知道了,但是直到今天我才真正意识到它的严重性.因为攻击者可以利用它来绕过Jinja2沙盒,这会造成严重的信息泄露问题.同时,我在本文最后部分为str.format提供了一个新的安全版本. 需要提醒的是,这是一个相当严重的安全隐患,这里之所以撰文介绍,是因为大多数人很可能不知道它是多么容

ArcGIS for Server 10.3.X 新型紧凑型缓存的解读和应用

早在2010年年底,牛魔王中王在其博客空间牛魔王的作坊中对ArcGIS 10中推出的紧凑型缓存格式进行了详细的解读,详见<ArcGIS 切片缓存紧凑文件格式分析与使用>.紧随着的4年时间里,ArcGIS for Server本身经历了10.10.1.X和10.2.X各版本的逐级更替,特别是软件架构发生了显著的变化.然而,就紧凑型缓存本身而言,牛魔王中王的解读一直都是适用的.衷心地向我们的大牛致敬! 直到2014年年底ArcGIS 10.3正式发布,Esri才推出了新的紧凑型缓存格式以增强用户的

3、Spring新型方式实现定时调度

1.实现和循环调度类似 public class QuartzJob3{ public void test(){ SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss"); System.out.println("Spring新型方法-使用定时触发器-被调用"+sdf.format(new Date())); } } 2.Spring配置如下 (1)注入调度类对象(注入2个类对象,用不同方式触发) <!-- 注