版权声明:欢迎神犇指教 https://blog.csdn.net/sdxtcqs/article/details/81813089
http://acm.hdu.edu.cn/showproblem.php?pid=3729
题意:n个人,每个人说自己排名在x~y名,问最多几个人说的是真话,输出最多的人数,和字典序最大的这几个人的编号。
数据范围:n <= 60,1 <= Xi <= Yi <= 100000
当时看到x,y的数据范围是有点被吓住了,但n只有60,而且我也不会什么其他方法,所以就对每个人对从Xi到Yi的每一个数都连一条边,然后暴力跑匈牙利算法,竟然卡过了,先T了几回,突然967ms卡过了,再后来再交又是T了,结果发现是因为我把vis数组开得太大了,每次匹配都要memset结果就疯狂T,真是太菜了。。。
而且上网查题解发现,发我的思路没错,就是要暴力,只是建图不需要每条边都存,记录一个x,y就行,每次遍历这个人的每条边就从x到y循环就行,这样空间也能省下很多。
这里还有一个点就是输出字典序最大的答案序列,其实很简单匹配的时候倒着循环,每次尽量先找大的,就能得到字典序最大的了。
还有个会PE的点就是每行末尾不能有空格,每组数据最后都有回车。
我的渣渣版本:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
#include <set>
using namespace std;
int ans[65];
int n,m,T,k;
bool vis[100005];//就是这个数组我之前多打了一个0就导致疯狂T
map<int,int> pr;
struct Edge{
int w,v,next;
}e[1000010];
int head[1000010];
void addedge(int u,int v,int w)
{
e[k].v=v;
e[k].w=w;
e[k].next=head[u];
head[u]=k++;
}
bool find(int x)
{
for(int i=head[x];i;i=e[i].next)
{
if(!vis[e[i].v])
{
vis[e[i].v]=1;
if(pr[e[i].v]==0||find(pr[e[i].v]))
{
pr[e[i].v]=x;
return 1;
}
}
}
return 0;
}
int main()
{
scanf("%d",&T);
while(T--)
{
k=1;
scanf("%d",&n);
int sum=0,num=0;
pr=map<int,int>();
memset(e,0,sizeof(e));
memset(head,0,sizeof(head));
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
for(int j=x;j<=y;j++)
addedge(i,j,1);
}
for(int i=n;i>=1;i--)//倒序循环
{
memset(vis,0,sizeof(vis));
if(find(i)) sum++;
}
printf("%d\n",sum);
map<int,int>::iterator it;
for(it=pr.begin();it!=pr.end();it++)
{
num++;
ans[num]=it->second;
}
sort(ans+1,ans+1+num);
for(int i=1;i<num;i++)
printf("%d ",ans[i]);
printf("%d",ans[num]);
printf("\n");
}
return 0;
}
借鉴题解后的改良版本
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
#include <set>
using namespace std;
int ans[65];
int n,m,T,k;
bool vis[100005];
map<int,int> pr;
struct Edge{
int x,y;
}e[100];//空间一下次省了好多
bool find(int p)
{
for(int i=e[p].x;i<=e[p].y;i++)
{
if(!vis[i])
{
vis[i]=1;
if(pr[i]==0||find(pr[i]))
{
pr[i]=p;
return 1;
}
}
}
return 0;
}
int main()
{
scanf("%d",&T);
while(T--)
{
k=1;
scanf("%d",&n);
int sum=0,num=0;
pr=map<int,int>();
memset(e,0,sizeof(e));
for(int i=1;i<=n;i++)
scanf("%d%d",&e[i].x,&e[i].y);
for(int i=n;i>=1;i--)
{
memset(vis,0,sizeof(vis));
if(find(i)) sum++;
}
printf("%d\n",sum);
map<int,int>::iterator it;
for(it=pr.begin();it!=pr.end();it++)
{
num++;
ans[num]=it->second;
}
sort(ans+1,ans+1+num);
for(int i=1;i<num;i++)
printf("%d ",ans[i]);
printf("%d",ans[num]);
printf("\n");
}
return 0;
}