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;
}