[CF 732F]Tourist Reform

Description

给出一张n个点,m条边的无向联通图,现在你要给每条边一个方向,设f(x)表示x所能到达的点的数量,你需要使得最小的f(x)最大。
求一种方案。
n,m<=4*10^5

Solution

这道题一点都不像F题(毕竟div.2)
首先,处于同一个点双中的点都可以互相到达。
于是先考虑双联通缩点,我们就得到了一棵树。
每个点的点权就是它所在的点双的大小。
现在我们就是要给每条树边一个方向。
毕竟你可以二分,但是还是有更简单的做法。
树嘛~~就有n-1条边,n个点,对不对?
也就是说,我们所有的点的出度和就是n-1?
那么就意味着有一个点一定没有出边!!
如果没有出边的话,那么它的大小就不会改变。
我们要让最小值最大。。。
那么我们就让这个没有出边的点是最大的那个点双就好啦。。
因为其他所有点都可以指向这个点。。。
那么就解决了,构造方案随便写写就好了2333

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a) for(int i=last[a];i;i=next[i])
using namespace std;
const int N=4*1e5+5;
int n,m,l,id,tot,root,mx,c[N],x[N],y[N],dfn[N],low[N],d[N];
int last[N],next[N*2],t[N*2],mark[N*2];
bool to[N],bz[N],g[N*2];
void add(int x,int y,int z) {
    t[++l]=y;mark[l]=z;next[l]=last[x];last[x]=l;
}
void tarjan(int x) {
    dfn[x]=low[x]=++tot;d[tot]=x;bz[x]=1;
    rep(i,x) if (!g[i]) {
        g[i]=g[i^1]=1;
        if (y[mark[i]]!=t[i]) to[mark[i]]=1;
        if (!dfn[t[i]]) {
            tarjan(t[i]);
            low[x]=min(low[x],low[t[i]]);
        } else if (bz[t[i]]) low[x]=min(low[x],dfn[t[i]]);
    }
    if (dfn[x]==low[x]) {
        id++;int size=0;
        while (d[tot+1]!=x) {
            c[d[tot]]=id;size++;
            bz[d[tot--]]=0;
        }
        if (size>mx) mx=size,root=id;
    }
}
void dfs(int x,int z) {
    rep(i,x) if (t[i]!=z) {
        if (c[y[mark[i]]]==t[i]) to[mark[i]]=1;
        else to[mark[i]]=0;
        dfs(t[i],x);
    }
}
int main() {
    scanf("%d%d",&n,&m);l=1;
    fo(i,1,m) scanf("%d%d",&x[i],&y[i]),add(x[i],y[i],i),add(y[i],x[i],i);
    tarjan(1);printf("%d\n",mx);
    memset(last,0,sizeof(last));l=0;
    fo(i,1,m) if (c[x[i]]!=c[y[i]]) add(c[x[i]],c[y[i]],i),add(c[y[i]],c[x[i]],i);
    dfs(root,0);
    fo(i,1,m) {
        if (to[i]) swap(x[i],y[i]);
        printf("%d %d\n",x[i],y[i]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值