LGJOI - 竞赛图【题解】
题意:一张竞赛图,你需要给每条边定向。然后进行 \(m\) 次边翻转,每次翻转边 \((u_i,v_i)\),你需要保证你构造的图在任何时候都不是强连通图。
\(1\le n\le 400,\space 0\le m\le 2n-14\)
考虑挖出一个连通块,这个连通块内的所有点总是向外连边,这样既可满足图永远不强连通的条件。
“挖连通块”非常抽象,具体的,我们先枚举第一个激活的点,用 \(vis[u]=0/1\) 表示 \(u\) 是否被激活。
依次枚举翻转的边,若这条边连的两个点有一个被激活,那么另一个也会被激活。最后判断是否存在未被激活的点,若是则枚举的点合法。
然后考虑构造,仍然枚举翻转的边。挖出的连通块内的边和连通块外的边方向随意,我们只需考虑连通块内的点与连通块外的点连接的边。
每激活一个点,我们确定一下令该点对当前连通块外的边的方向。注意考虑的边可能已经翻转过,所以还要记录每条边是否翻转过。
不会证,官方题解写得依托答辩。
#include<bits/stdc++.h>
#define pr pair<ll,ll>
#define x first
#define y second
#define mkp(a,b) make_pair(a,b)
#define pb push_back
#define ll long long
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
using namespace std;
const ll maxn=410;
ll n,m,w[maxn][maxn],ans[maxn][maxn],vis[maxn];
pr a[maxn];
void upd(ll x)
{
for(ll i=1;i<=n;i++)
if(!vis[i])
{
ans[x][i]=w[x][i]^1;
ans[i][x]=w[x][i];
}
}
int main()
{
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=m;i++)
{
scanf("%lld%lld",&a[i].x,&a[i].y);
}
for(ll i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
vis[i]=1;
for(ll j=1;j<=m;j++)
{
pr e=a[j];
if(vis[e.x]||vis[e.y])
vis[e.x]=vis[e.y]=1;
}
if(count(vis+1,vis+1+n,0))
{
memset(vis,0,sizeof vis);
vis[i]=1; upd(i);
break;
}
}
for(ll i=1;i<=m;i++)
{
pr e=a[i];
w[e.x][e.y]^=1; w[e.y][e.x]^=1;
if(vis[e.x]||vis[e.y])
{
if(!vis[e.x]) upd(e.x);
else if(!vis[e.y]) upd(e.y);
vis[e.x]=vis[e.y]=1;
}
}
for(ll i=1;i<=n;i++)
{
for(ll j=i+1;j<=n;j++)
printf("%lld ",ans[i][j]);
printf("\n");
}
return 0;
}