sgu101 欧拉路径 难度:1
101. Domino
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The blocks usually are called bones, dominoes, or pieces and sometimes men, stones, or even cards.
The face of each piece is divided, by a line or ridge, into two squares, each of which is marked as would be a pair of dice...
The principle in nearly all modern dominoes games is to match one end of a piece to another that is identically or reciprocally numbered.
ENCYCLOPÆDIA BRITANNICA
Given a set of domino pieces where each side is marked with two digits from 0 to 6. Your task is to arrange pieces in a line such way, that they touch through equal marked sides. It is possible to rotate pieces changing left and right side.
Input
The first line of the input contains a single integer N (1 ≤ N ≤ 100) representing the total number of pieces in the domino set. The following N lines describe pieces. Each piece is represented on a separate line in a form of two digits from 0 to 6 separated by a space.
Output
Write “No solution” if it is impossible to arrange them described way. If it is possible, write any of way. Pieces must be written in left-to-right order. Every of N lines must contains number of current domino piece and sign “+” or “-“ (first means that you not rotate that piece, and second if you rotate it).
Sample Input
5 1 2 2 4 2 4 6 4 2 1
Sample Output
2 - 5 + 1 + 3 + 4 -
思路:A:相同点数缩为一点,每个骨牌作为边连接两个点数,则每条边都必须走,这个时候根据欧拉迹的性质,找到度数为奇数的点作为起始点走一遍,或者没有奇数点随便找个点(此时欧拉回路),走一遍dfs遍历全图,看是否有边走不到(每个边只走一次)
WWA:错误原因:1 没有考虑到未联通的状态,直接判断必须是半欧拉图,这样只有一种点数的时候就错误
#include <cstdio>
#include <cstring> #include <vector> using namespace std; typedef pair<int,int> P; const int maxn=101; int n,s,e; int a[maxn][2]; vector <P> G[maxn]; int heap[maxn],len; bool vis[maxn]; int deg[maxn]; int stck[2*maxn],slen; bool used[2*maxn]; void dfs(int x){ for(int i=0;i<G[x].size();i++){//遍历从x出发能到达的点 if(!used[G[x][i].second]){ used[G[x][i].second]=true;//翻转和不翻转的状态都被遍历 used[G[x][i].second^1]=true; dfs(G[x][i].first);//欧拉路径性质:从一个点出发可以到达所有点,也就是说如果这个点还有没走的边必然会回到这个点 stck[--slen]=G[x][i].second; } } } void addedge(int from,int to,int ind){ G[from].push_back(P(to,2*ind));G[to].push_back(P(from,2*ind+1)); deg[from]++;deg[to]++; } int main(){ while(scanf("%d",&n)==1){ for(int i=0;i<maxn;i++)G[i].clear();//初始化 memset(used,0,sizeof(used)); memset(vis,0,sizeof(vis)); memset(deg,0,sizeof(deg)); len=slen=0; for(int i=0;i<n;i++){ scanf("%d%d",a[i],a[i]+1); if(!vis[a[i][0]]){heap[len++]=a[i][0];vis[a[i][0]]=true;}//去重 if(!vis[a[i][1]]){heap[len++]=a[i][1];vis[a[i][1]]=true;} } bool failed=false;s=e=-1; for(int i=0;i<n;i++){//以牌为边加边 addedge(a[i][0],a[i][1],i); } for(int i=0;i<len;i++){ if(deg[heap[i]]&1){//奇数度点选作起点终点 if(s==-1)s=heap[i]; else if(e==-1)e=heap[i]; else failed=true; } } if(failed){ puts("No solution"); } else { if(s==-1)s=heap[0];//欧拉回路任选一个作为起点 slen=n; dfs(s); if(slen!=0)puts("No solution");//有边没有遍历到 else for(int i=0;i<n;i++){ printf("%d ",stck[i]/2+1); printf("%c\n",stck[i]&1?'-':'+');//状态2k为原来状态,2k+1则翻转
} } } return 0; }