【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=1689
【题目大意】
给定N个珠子,从1到N编号,然后是M个配对关系(x,y),表示珠子x和y可以相邻,要求用最少的珠子组成串,且所用珠子个数是大于或等于3的奇数,求这个最小的珠子个数的值。
【详细分析】
刚开始看到题,是自己刚刚挂的一个DIY:2008“Sunline Cup”邀请赛里的第一题,大概的想了下,觉得可以转换成最小环来做,刚好自己会最小环(可以参考我的最小环相关博文,很详细)。数据量是1000,觉得Floyd算法应该可以吧,就写了,结果是超时。赛后自己百度,看了很多讲解,下面给出整理之后的详细题解。
(待要到100ms以内的代码再行补之,见谅)
【AC代码】
/*2011-02-06 19:39:27 Accepted 1689 437MS 588K 1884 B C++ *///http://www.cnblogs.com/zhuangli/articles/1285516.html
#include<iostream>#include<stdio.h>#include<queue>using namespace std;struct Edge{ int next,v;}edge[40010];int idx;int n,m,dp[1005],p[1005]; bool vis[1005];struct Node{int v;};queue<Node>Q;queue<Node>save;void Addedge(int a,int b){ edge[idx].next=p[a]; edge[idx].v=b; p[a]=idx++;} void BFS(){ int i,res=INT_MAX; for(i=1;i<=n;i++){ while(!Q.empty()) Q.pop(); memset(vis,0,sizeof(vis)); Node st; st.v=i; dp[i]=0; Q.push(st); vis[i]=1; int len=0,j,v; while(!Q.empty()&& ++len<res){ while(!save.empty()) save.pop(); while(!Q.empty()){ //逐层扩展; Node t=Q.front(); Q.pop(); for(j=p[t.v];j!=-1;j=edge[j].next){ v=edge[j].v; if(vis[v]){ int now=dp[v]+len; if(now<res&&now&1) res=now; } else{ Node tt; tt.v=v; save.push(tt); vis[v]=1; dp[v]=len; } } } while(!save.empty()){ Q.push(save.front()); save.pop(); } } } if(res==INT_MAX) puts("Poor JYY."); else printf("JYY has to use %ld balls./n",res); }int main(){ int T,x,y,TT=0; scanf("%d",&T); while(T--) { memset(p,-1,sizeof(p)); scanf("%d%d",&n,&m); idx=0; while(m--){ scanf("%d%d",&x,&y); Addedge(x,y); swap(x,y); Addedge(x,y); } printf("Case %d: ",++TT); BFS(); }}