程序员的资源宝库

网站首页 > gitee 正文

「九省联考 2018」劈配 解题报告

sanyeah 2024-03-30 13:07:21 gitee 13 ℃ 0 评论

「九省联考 2018」劈配

写了一个有点奇怪的做法(感觉

首先发现有个比较正常的暴力,就是每次二分重新建图跑,似乎有80分,应该也比较好写,考场应该会写这个。

考虑如果得到了前\(i\)个人的答案(问题1),那么这些人只能在一部分的导师里面反悔,我们把这些边建出来。

然后对于\(i+1\sim n\)个人,每次把它所有边加上,然后看看它在这个排名可不可以达到它的期望,然后再把边撤回。

这里用一个单路增广就好,比较好撤回,可以发现这个单路增广是\(O(n+m)\)

然后每个人跑了\(n\)次单路增广,\(m\)在建一部分边后大小应该是\(nc\)条的,所以总复杂度是\(O(Tn^3C)\),跑不满就可以过


Code:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
const int N=420;
const int M=4e5;
const int inf=0x3f3f3f3f;
template <class T>
void read(T &x)
{
	x=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
int head[N],thead[N],edge[M],to[M],Next[M],cnt;
void add(int u,int v,int w)
{
	to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
	to[++cnt]=u,edge[cnt]=0,Next[cnt]=head[v],head[v]=cnt;
}
int n,m,s,t,bee[N][N],ans0[N],ans1[N],yuy[N];
int pre[N],vis[N],ti,Id,flag;
void dfs(int now)
{
    vis[now]=ti;
    if(now==t)
    {
        while(pre[now])
        {
            if((now>n&&now<=n+m)||now==t+1) Id=now;
            now=to[pre[now]^1];
        }
        flag=0;
        return;
    }
    for(int v,i=head[now];flag&&i;i=Next[i])
        if(edge[i])
        {
            if(vis[v=to[i]]==ti) continue;
            pre[v]=i;
            dfs(v);
        }
}
struct koito_yuu
{
	int v,x;//第几志愿,节点标号
	koito_yuu(){}
	koito_yuu(int V,int X){v=V,x=X;}
	bool friend operator <(koito_yuu a,koito_yuu b){return a.v>b.v;}
}yuu[N][N];
void work()
{
	read(n),read(m);
	s=n+m+1,t=s+1;
	for(int b,i=1;i<=m;i++) read(b),add(i+n,t,b);
	add(t+1,t,inf);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)//第i个人对第j个导师为第几志愿
			read(bee[i][j]),yuu[i][j]=koito_yuu(bee[i][j],j+n);
		bee[i][m+1]=m+1,yuu[i][m+1]=koito_yuu(m+1,t+1);
		std::sort(yuu[i]+1,yuu[i]+1+m+1);
		/*a[j]=mp(bee[i][j],j);
		std::sort(a+1,a+1+m);
		a[m+1]=mp(m+1,t+1);
		bee[i][m+1]=m+1;
		for(int j=m;~j;j--)
			if(a[j].fisrt!=a[j+1].fisrt)
			{
				endro[i][a[j+1].fisrt]=head[i];//第i个人第j个志愿的
				if(a[j].fisrt) add(i,a[j].second,1);
			}
		*/
	}
	for(int i=1;i<=n;i++) read(yuy[i]);
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=n;j++)
		{
			int tmp=cnt;
			for(int k=1;k<=t+1;k++) thead[k]=head[k];
			add(s,j,1);
			for(int k=1;k<=m+1;k++)
			{
				if(!yuu[j][k].v) break;
				add(j,yuu[j][k].x,1);
			}
			flag=1,++ti;
			dfs(s);
			Id=bee[j][Id==t+1?m+1:Id-n];
			if(j==i) ans0[i]=Id;
			if(Id<=yuy[j]) ans1[j]=i;
			cnt=tmp;
			for(int k=1;k<=t+1;k++) head[k]=thead[k];
		}
		add(s,i,1);
		for(int j=1;j<=m+1;j++)
			if(ans0[i]==yuu[i][j].v)
				add(i,yuu[i][j].x,1);
        flag=1,++ti;
        dfs(s);
		int now=t;
		while(pre[now])
		{
			--edge[pre[now]];
			++edge[pre[now]^1];
			now=to[pre[now]^1];
		}
	}
    for(int i=1;i<=n;i++) printf("%d ",ans0[i]);
    puts("");
	for(int i=1;i<=n;i++) printf("%d ",i-ans1[i]);
	puts("");
}
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
	int T,C;
	read(T),read(C);
	while(T--)
	{
		//待会清空放在这里,要检查
		memset(head,0,sizeof head);
        memset(pre,0,sizeof pre);
        memset(ans1,0,sizeof ans1);
		cnt=1;
		work();
	}
	return 0;
}

2019.3.19

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表