【題目連結】
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();
}
}