BZOJ 1006 [HNOI2008]神奇的国度==最大势算法

来源:互联网 发布:营销网络优势 编辑:程序博客网 时间:2024/04/20 06:15

题目链接:点我传送

算法初步:点我传送

算法证明:我不会且找不到

=====回归正题=====

首先大家一眼就看出来这道问题的实质:给你一个无向图,用最少的颜色染色,使得相连接的两个点颜色不同。

(不要告诉我有板子。

这种题目就要用到一种恒牛掰的算法=======最大势算法!!!

(第一反应==这什么鬼

(第二反应==百度

百度的童鞋萌,泥萌走出了正确的一步!!!

算法的主要思想是这样的:开始时每个点标记为零。

之后每次找剩下的元素中标记最大的点,删除,并且与这个点连接的点标记加一(已被删除的点标记不变)。

重复上一行直到所有元素被删除,所有点标记的种类数既是答案。

=====算法图示====

以该题样例为例。

开始时:标记全部为0.

①删除==之后(②④标记++)


②标记一个,最大之一,删除(③④++,①已被删除,标记不变)


④标记大于③,④删除③标记++


最后把③删除。

1--4共有0.1.2.2个标记,有0.1.2三种,输出3。

=====算法实现&优化=====点我传送=三楼正解

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <windows.h>#define rep(j,k,l) for (int j=k;j<=l;j++)using namespace std;int ne[2222222],to[2222222],st[11111],used[11111];int stt[11111],too[6666666],next[6666666],lych[11111],du[11111];int n,m;void add(int k,int l,int i){to[i]=l;ne[i]=st[k];st[k]=i;}int main(){scanf("%d%d",&n,&m);rep(i,1,m){int k,l;scanf("%d%d",&k,&l);add(k,l,i*2-1);add(l,k,i*2);}memset(used,0,sizeof(used));rep(i,1,n) next[i]=i-1,too[i]=i;stt[0]=n;int num=0,best=0,mm=n;while (num!=n){if (stt[best]==0){best--;continue;}if (used[too[stt[best]]]==0){int x=too[stt[best]];used[too[stt[best]]]=1;stt[best]=next[stt[best]];lych[du[x]]=1;num++;best=best<=du[x]?du[x]:best;//printf("%d\n",x);for (int i=st[x];i!=0;i=ne[i]){if (used[to[i]]==0){du[to[i]]++;//printf("%d %d\n",to[i],du[to[i]]);//printf("%d %d\n",du[to[i]],best);next[++mm]=stt[du[to[i]]];too[mm]=to[i];stt[du[to[i]]]=mm;lych[du[to[i]]]=1;best=best<=du[to[i]]?du[to[i]]:best;//printf("%d233\n",best);//printf("%d\n",ne[i]);}}}else stt[best]=next[stt[best]];}//rep(i,1,mm) printf("%d %d\n",to[i],ne[i]);//rep(i,1,n) printf("%d\n",st[i]);int aaa=0;rep(i,0,n) aaa+=lych[i];//printf("%d %d\n",i,lych[i]);printf("%d\n",aaa);system("pause");return 0;}


0 0
原创粉丝点击