POJ3697+BFS+hash存边

  1 /*
  2 疾速优化+hash存边
  3 题意:给定一个包含N(1 ≤ N ≤ 10,000)个顶点的无向完全图,图中的顶点从1到N依次标号。从这个图中去掉M(0 ≤ M ≤ 1,000,000)条边,求最后与顶点1联通的顶点的数目
  4 思路(BFS):从顶点1开始不断扩展,广度优先搜索所有的与当前扩展点联通的顶点。开始每次都要判断所有的顶点是否与cur相连,
  5   若相连则push,反之跳过。
  6 */
  7 #include<stdio.h>
  8 #include<string.h>
  9 #include<stdlib.h>
 10 #include<algorithm>
 11 #include<iostream>
 12 #include<queue>
 13 #include<map>
 14 #include<stack>
 15 #include<set>
 16 #include<math.h>
 17 using namespace std;
 18 typedef long long int64;
 19 //typedef __int64 int64;
 20 typedef pair<int64,int64> PII;
 21 #define MP(a,b) make_pair((a),(b)) 
 22 const int maxn = 10005;
 23 const int maxm = 1200005;
 24 const int smod = 10091;
 25 const int mod = 1000117;
 26 const int inf = 0x7fffffff;
 27 const double pi=acos(-1.0);
 28 const double eps = 1e-8;
 29 
 30 struct Edge{
 31     int u,v,next;
 32 }edge[ maxm<<1 ];
 33 int cnt,myhash[ maxm<<1 ];
 34 queue<int>q;
 35 int vis[ maxn ];
 36 
 37 void init(){
 38     cnt = 0;
 39     while( !q.empty() )
 40         q.pop();
 41     memset( myhash,-1,sizeof( myhash ) );
 42 }
 43 
 44 void addedge( int a,int b ){
 45     //if( a>b ) swap( a,b );
 46     int tt = (a*smod+b)%mod;
 47     edge[ cnt ].u = a;
 48     edge[ cnt ].v = b;
 49     edge[ cnt ].next = myhash[ tt ];
 50     myhash[ tt ] = cnt++;
 51     
 52     tt = (b*smod+a)%mod;
 53     edge[ cnt ].u = a;
 54     edge[ cnt ].v = b;
 55     edge[ cnt ].next = myhash[ tt ];
 56     myhash[ tt ] = cnt++;
 57     
 58 }
 59 
 60 bool find( int u,int v ){
 61     //if( u>v ) swap( u,v );
 62     int tt = ( u*smod+v )%mod;
 63     for( int i=myhash[tt];i!=-1;i=edge[i].next ){
 64         if( edge[ i ].u == u && edge[ i ].v == v ){
 65             return true;
 66         }
 67     }
 68     return false;
 69 }
 70 
 71 int main(){
 72     int n,m;
 73     int Case = 1;
 74     while( scanf("%d%d",&n,&m)==2,n+m ){
 75         init();
 76         int x,y;
 77         while( m-- ){
 78             scanf("%d%d",&x,&y);
 79             addedge( x,y );
 80             addedge( y,x );
 81         }
 82         int ans = 0;
 83         cnt = 0;
 84         q.push( 1 );
 85         for( int i=2;i<=n;i++ ){
 86             vis[ cnt++ ] = i;
 87         }
 88         while( !q.empty() ){
 89             int cur = q.front();
 90             q.pop();
 91             int tmp_cnt = 0;
 92             for( int i=0;i<cnt;i++ ){
 93                 if( !find( cur,vis[i] ) ){
 94                     ans ++;
 95                     q.push( vis[i] );
 96                 }
 97                 else  vis[ tmp_cnt++ ] = vis[i];
 98             }
 99             cnt = tmp_cnt;
100         }
101         printf("Case %d: %d\n",Case++,ans);
102     }
103     return 0;
104 }
View Code

 

转载于:https://www.cnblogs.com/xxx0624/p/3275296.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值