I Interesting Computer Game 2020牛客暑期多校训练营(第八场)

https://ac.nowcoder.com/acm/contest/5673/I

上周才做了一道二分图匹配用dinic跑复杂度是msqrt(n)的题,这里t=10过不了3n个点2n条边过不了,T了好久最后写了个贪心,但不会证明正确性。。。

对于每个数字,统计他在多少个位置出过,然后找到他与哪些数字在同一个位置过

我们每次找出当前出线次数最小的数字u,然后扫一遍他冲突的数字,其中没有被选取的中剩余出线最多的v,就选那个u和v冲突的位置,让sum[v]--,这样一直做下去直到没有数字可选。用set维护找出最少的数字

#include<bits/stdc++.h>
namespace FastIO {
    const int SIZE = 1 << 16;
    char buf[SIZE], obuf[SIZE], str[60];
    int bi = SIZE, bn = SIZE, opt;
    int read(char *s) {
        while (bn) {
            for (; bi < bn && buf[bi] <= ' '; bi++);
            if (bi < bn) break;
            bn = fread(buf, 1, SIZE, stdin);
            bi = 0;
        }
        int sn = 0;
        while (bn) {
            for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
            if (bi < bn) break;
            bn = fread(buf, 1, SIZE, stdin);
            bi = 0;
        }
        s[sn] = 0;
        return sn;
    }
    bool rd(int& x) {
        int n = read(str), bf;
        if (!n) return 0;
        int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
        for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
        if (bf < 0) x = -x;
        return 1;
    }
};
using namespace FastIO;
using namespace std;

const int maxl=3e5+10;
const int inf=2e9;

int S,T,n,tot,cas,cnt,ans;
int a[maxl],b[maxl],c[maxl],sum[maxl];
typedef pair<int,int> p;
set<p> s;
vector<int>e[maxl];
bool in[maxl];

inline int id(int x)
{
	return lower_bound(c+1,c+1+tot,x)-c;
}

inline void prework()
{
	//scanf("%d",&n);
	rd(n);
	tot=0;int aa,bb;
	for(register int i=1;i<=n;++i)
	{
		//scanf("%d%d",&a[i],&b[i]);
		rd(a[i]);rd(b[i]);
		c[++tot]=a[i];c[++tot]=b[i];
	}
	sort(c+1,c+1+tot);
	tot=unique(c+1,c+1+tot)-c-1;
	for(int i=1;i<=tot;++i)
		sum[i]=0,e[i].clear();
	for(int i=1;i<=n;++i)
	if(a[i]==b[i])
		++sum[id(a[i])];
	else 
	{
		aa=id(a[i]);bb=id(b[i]);
		++sum[aa],++sum[bb];
		e[aa].push_back(bb);
		e[bb].push_back(aa);
	}
	s.clear();
	for(int i=1;i<=tot;i++)
		s.insert({sum[i],i}),in[i]=true;
}

inline void mainwork()
{
	int u,v,id,mx;ans=0;p d;
	while(s.begin()!=s.end())
	{
		d=(*s.begin());
		if(d.first==0) break;
		u=d.second;in[u]=false;++ans;
		s.erase(s.begin());
		mx=0,id=0;
		for(int v:e[u])
		if(in[v] && sum[v]>mx)
			id=v,mx=sum[v];
		if(id!=0)
		{
			s.erase(s.lower_bound({sum[id],id}));
			--sum[id];
			if(sum[id]==0) in[id]=false;
			else s.insert({sum[id],id});
		}
	}
}

inline void print()
{
	printf("Case #%d: %d\n",cas,ans);
}

int main()
{
	int t;
	//scanf("%d",&t);
	rd(t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/107768046