zoukankan      html  css  js  c++  java
  • 「九省联考 2018」劈配 解题报告

    「九省联考 2018」劈配

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

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

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

    然后对于(i+1sim 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

  • 相关阅读:
    Java Socket编程(三)发送和接收深入
    Java温故知新 集合类
    DataTable到实体类的转换 中庸
    经典设计模式
    门面模式
    java经典反射机制(1)
    装饰模式
    单子模式
    sql经典题目(1)
    如何学习struts框架?
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10556380.html
Copyright © 2011-2022 走看看