2 5 6 1 2 2 4 1 3 3 5 4 3 4 5 2 1 1 2
Case 1: JYY has to use 3 balls. Case 2: Poor JYY.
題意:讓找到一個環使得組成環的點數為奇數且點數至少為3,。
因為一個點可以多個途徑到達,但從一點出發第一次到達的肯定是最短路徑,又題目要求的奇偶性,每次到達一個點步數的奇偶性進行標記。
#include#include #include #include #include using namespace std; #define N 1005 #define ll __int64 const int inf=0x7fffffff; vector g[N]; int vis[N][2]; struct node { int u,t; friend bool operator<(node a,node b) { return a.t>b.t; } }; int bfs(int s) { int i,u,v; priority_queue q; node cur,next; cur.u=s; cur.t=1; memset(vis,0,sizeof(vis)); vis[s][1]=1; //奇數點,用一個珠子 q.push(cur); while(!q.empty()) { cur=q.top(); q.pop(); u=cur.u; for(i=0;i 3) //結點處到達兩次,故應該減一 return next.t-1; if(!vis[v][next.t%2]) { vis[v][next.t%2]=1; q.push(next); } } } return inf; } int main() { int i,n,m,u,v,tt,cnt=0; scanf("%d",&tt); while(tt--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) g[i].clear(); while(m--) { scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } int ans=inf; for(i=1;i<=n;i++) ans=min(ans,bfs(i)); if(ans==inf) printf("Case %d: Poor JYY.\n",++cnt); else printf("Case %d: JYY has to use %d balls.\n",++cnt,ans); } return 0; }
下面這種方法是用一個數組記錄到達該點的步數,當再次訪問該點時,說明出現環,直接判斷奇偶性就可以了。
又要求所用珠子數目大於三,所以要用一個pre變量記錄上一個節點的標號,判斷是否是兩點直接成環。
#include#include #include #include #include using namespace std; #define N 1005 #define ll __int64 const int inf=0x7fffffff; vector g[N]; int vis[N][2]; int ans; struct node { int u,t,pre; friend bool operator<(node a,node b) { return a.t>b.t; } }; int bfs(int s) { int i,u,v,t; priority_queue q; node cur,next; cur.u=s; cur.t=1; cur.pre=-1; memset(vis,0,sizeof(vis)); vis[s][1]=1; q.push(cur); while(!q.empty()) { cur=q.top(); q.pop(); u=cur.u; for(i=0;i