Gym

来源:互联网 发布:crm php开源系统源码 编辑:程序博客网 时间:2024/06/04 19:00

http://codeforces.com/gym/101597/problem/D
这种搜索不像是普通的搜索,更像是一种思维题。
并且题目有一个暗示:
输出的集合只要满足条件就行,没有说最大还是最小。


给定一个图,要求你求一个集合。
x(集合里的数)-k(大小)>=(集合中任意点相邻的最大距离)
要求你输出这个集合。
集合中最小的为2。
我开的思路是对每个点bfs。然后记录他们各个层数的点的数目,然后求一下前缀,
就用该前缀x-k >=j,然后我们就可以输出
但是再处理样例的时候,我发现每两个层次为j的点距离为2。
然后就wa了。
因为两个层次为j的点距离可能并不为2*j,因为他们俩可能直接相连(这是我后来看的数据)
正解:对每个点bfs。然后保存每个点的层数值,维护一个最大值。可以保证如果 所有的点 n-k>=max,那么其他就成立,输出1-n.否则就不可以。
简易的证明:
如果对于x个点(x<=n) 存在x-k>=max, 那么x增加一个点。最多到最max+1。那么 (x+1)-k>=(max+1) 依然成立。所以增加到n也是成立的。并且再实际情况中 max并不一定会增加1。这时考虑最差的情况。


#include <bits/stdc++.h>using namespace std;const int maxn=5005;vector<int>G[maxn];vector<int>num[maxn];int d[maxn];bool vis[maxn];int m;int bfs(int x){   for(int i=0;i<maxn;i++)       num[i].clear();   queue< pair<int,int> >q;   memset(vis,false,sizeof(vis));   memset(d,0,sizeof(d));   vis[x]=true;   d[x]=0;   q.push(make_pair(x,0));   while(!q.empty()){       pair<int,int>u=q.front();       q.pop();       d[u.first]=u.second;       for(int i=0;i<G[u.first].size();i++){          int to=G[u.first][i];          if(!vis[to]){             vis[to]=true;             q.push(make_pair(to,u.second+1));          }       }   }   int ans=-1;   for(int i=1;i<=m;i++){     ans=max(d[i],ans);   }return ans;}int main(){   int n,k,a,b;     scanf("%d%d%d",&m,&n,&k);     for(int i=0;i<n;i++){         scanf("%d%d",&a,&b);         G[a].push_back(b);         G[b].push_back(a);     }     int rel=-1;     for(int i=1;i<=m;i++){         rel=max(bfs(i),rel);     }     if(rel<=m-k){        printf("%d\n",m);             for(int j=1;j<=m;j++){                  if(j==1)                  printf("%d",j);                  else                  printf(" %d",j);            }        cout<<endl;     }     else{        puts("0");     }    return 0;}
原创粉丝点击