↓ Skip to main content
  1. Posts/

poj 1386 Play on Words (欧拉路)

·661 words·2 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

poj 1386

题意:n个单词,问能否形成一个串(单词接龙,收尾相连,当且仅当前一个单词的末尾字母和后一个单词的首字母相同)

思路:欧拉路。

关于欧拉路:

(1)有向图G为欧拉图(存在欧拉回路),当且仅当G的基图连通(弱联通,),且所有顶点的入度等于出度。

(2)有向图G为半欧拉图(存在欧拉路),当且仅当G的基图连通(弱联通),且存在顶点u的入度比出度大1、v的入度比出度小1,其它所有顶点的入度等于出度。

(3) 无向图存在欧拉回路: 图连通,所有点都是偶数度,

(4)无向图存在欧拉路:图联通,只有两个点的度数为奇数。

有向图判断联通性判断的弱联通,因此可以用并查集实现。

具体办法是,判断根的个数,个数为大于1表示不联通。

代码实现
  1#include <cstdio>
  2#include <cstring>
  3#include <iostream>
  4#include <algorithm>
  5#include <vector>
  6#include <queue>
  7#include <set>
  8#include <map>
  9#include <string>
 10#include <cmath>
 11#include <cstdlib>
 12#include <ctime>
 13#define fst first
 14#define sec second
 15#define lson l,m,rt<<1
 16#define rson m+1,r,rt<<1|1
 17#define ms(a,x) memset(a,x,sizeof(a))
 18typedef long long LL;
 19#define pi pair < int ,int >
 20#define MP make_pair
 21using namespace std;
 22const double eps = 1E-8;
 23const int dx4[4]={1,0,0,-1};
 24const int dy4[4]={0,-1,1,0};
 25const int inf = 0x3f3f3f3f;
 26const int N=26;
 27int in[N];
 28int out[N];
 29int f[N];
 30int root ( int x)
 31{
 32    if (x!=f[x]) f[x] = root(f[x]);
 33    return f[x];
 34}
 35void merge( int x,int y)
 36{
 37    int rx = root(x);
 38    int ry = root(y);
 39    if (rx!=ry)
 40	f[rx] = ry;
 41}
 42void init()
 43{
 44    for ( int i = 0 ; i < N ;  i++) f[i] =  i;
 45    ms(in,0);
 46    ms(out,0);
 47}
 48int n ;
 49set<int>se;
 50bool Euler()
 51{
 52    int a,b;
 53    a=b=0;
 54    set<int>::iterator it;
 55    for ( it = se.begin() ;it!=se.end() ; it++)
 56    {
 57	int i = *it;
 58	if (in[i]==out[i]+1)a++;
 59	else if (out[i]==in[i]+1) b++;
 60	else if (out[i]!=in[i]) return false;
 61    }
 62    if (a+b==0||(a==1&&b==1)) return true;
 63    return false;
 64}
 65int main()
 66{
 67	#ifndef  ONLINE_JUDGE
 68	freopen("code/in.txt","r",stdin);
 69  #endif
 70	int T;
 71	cin>>T;
 72	while (T--)
 73	{
 74	    init();
 75	    scanf("%d",&n);
 76	    se.clear();
 77	    for ( int i = 0 ; i < n ; i++)
 78	    {
 79		char st[1005];
 80		scanf("%s",st);
 81		int len = strlen(st);
 82		int u = st[0]-'a';
 83		int v = st[len-1]-'a';
 84		merge(u,v);
 85		out[u]++;
 86		in[v]++;
 87		se.insert(v);
 88		se.insert(u);
 89	    }
 90	    int cnt = 0 ;
 91	    bool die = false;
 92	    for (set<int>::iterator it = se.begin() ; it!=se.end() ; it++)
 93	    {
 94		if (f[*it]==*it) cnt++;
 95		if (cnt>1)
 96		{
 97		    die = true;
 98		    break;
 99		}
100	    }
101	    if (!Euler()) die = true;
102	    if (die)
103	    {
104		puts("The door cannot be opened.");
105	    }
106	    else
107	    {
108		puts("Ordering is possible.");
109	    }
110	}
111  #ifndef ONLINE_JUDGE
112  fclose(stdin);
113  #endif
114    return 0;
115}

Related

poj 1383 Labyrinth (树的直径裸题)

·393 words·1 min
poj 1383题目链接 题意:一个迷宫图,求最远两点的距离是多少,保证每两个点都是联通的。 思路:树的直径。 代码实现 1#include <cstdio> 2#include <cstring> 3#include <iostream> 4#include <algorithm> 5#include <vector> 6#include <queue> 7#include <set> 8#include <map> 9#include <string> 10#include <cmath> 11#include <cstdlib> 12#include <ctime> 13#define fst first 14#define sec second 15#define lson l,m,rt<<1 16#define rson m+1,r,rt<<1|1 17#define ms(a,x) memset(a,x,sizeof(a)) 18typedef long long LL; 19#define pi pair < int ,int > 20#define MP make_pair 21using namespace std; 22const double eps = 1E-8; 23const int dx4[4]={1,0,0,-1}; 24const int dy4[4]={0,-1,1,0}; 25const int inf = 0x3f3f3f3f; 26const int N=1E3+7; 27char maze[N][N]; 28bool vis[N][N]; 29int ans; 30int n,m; 31struct Point 32{ 33 int x,y; 34 int d; 35 bool ok () 36 { 37 if (x<0||y<0||x>=n||y>=m) return false; 38 if (maze[x][y]=='#') return false; 39 if (vis[x][y]) return false; 40 return true; 41 } 42 void out() 43 { 44 cout<<"x:"<<x<<" y:"<<y<<endl; 45 } 46}S,lst; 47void bfs(Point S) 48{ 49 queue<Point>q; 50 S.d = 0; 51 q.push(S); 52 ms(vis,false); 53 vis[S.x][S.y] = true; 54 while (!q.empty()) 55 { 56 Point cur = q.front(); 57 q.pop(); 58 for ( int i = 0 ; i < 4 ; i++) 59 { 60 Point nxt; 61 nxt.x = cur.x + dx4[i]; 62 nxt.y = cur.y + dy4[i]; 63 nxt.d = cur.d + 1; 64 if (!nxt.ok()) continue; 65 q.push(nxt); 66 vis[nxt.x][nxt.y] = true; 67 if (ans<nxt.d) 68 { 69 ans = nxt. d; 70 lst = nxt; 71 } 72 } 73// cout<<"ans:"<<ans<<endl; 74 } 75} 76int main() 77{ 78 #ifndef ONLINE_JUDGE 79 freopen("code/in.txt","r",stdin); 80 #endif 81 int T; 82 cin>>T; 83 while(T--) 84 { 85 ms(vis,false); 86 scanf("%d%d",&m,&n); 87 for ( int i = 0; i < n ; i++) scanf("%s",maze[i]); 88 for ( int i = 0 ; i < n ; i++) 89 for ( int j = 0 ; j < m ; j++) 90 if (maze[i][j]=='.') 91 { 92 S.x = i ; 93 S.y = j ; 94 } 95 ans = 0; 96 bfs(S); 97 ans = 0 ; 98 bfs(lst); 99 printf("Maximum rope length is %d.\n",ans); 100 } 101 #ifndef ONLINE_JUDGE 102 fclose(stdin); 103 #endif 104 return 0; 105}

poj 1379 Run Away (模拟退火)

·546 words·2 mins
poj 1379题目链接 题意:给出一个矩形区域的长宽,给出区域中若干点,问距离所有点的最近距离的最大值是多少。 思路:很容易想到模拟退火。 比赛的时候因为忘记判断矩形边界导致答案错得离谱2333

seerc 2014 Circle of digits (二分+后缀数组)

·979 words·2 mins
题目链接 题意:把一个长度为 n 的只由数字构成的串分成 k 个不为空的子串,使得最大的串最小(大小是指串所对应的十进制数的大小)。 思路:由于长度为 x 的串肯定大于长度为 x-1 的串,因此很容易想到,我们要尽可能使得 k 组串的长度平均(避免出现某一个串的长度非常大的情况)。

seerc 2014 D - Frame (傻逼题)

·232 words·1 min
题目链接 思路:注意xy-(x-2)*(y-2)=2x+2y-4,一定被2整除。因此siz为2的也是合法的。这个比较容易忘掉。 其他的判定条件都很好想。具体见代码; 代码实现 1#include <cstdio> 2#include <cstring> 3#include <iostream> 4#include <algorithm> 5#include <vector> 6#include <queue> 7#include <set> 8#include <map> 9#include <string> 10#include <cmath> 11#include <cstdlib> 12#include <ctime> 13#define fst first 14#define sec second 15#define lson l,m,rt<<1 16#define rson m+1,r,rt<<1|1 17#define ms(a,x) memset(a,x,sizeof(a)) 18typedef long long LL; 19#define pi pair < int ,int > 20#define MP make_pair 21using namespace std; 22const double eps = 1E-8; 23const int dx4[4]={1,0,0,-1}; 24const int dy4[4]={0,-1,1,0}; 25const int inf = 0x3f3f3f3f; 26int X,Y; 27bool ok( int a) 28{ 29 if (a==2) return true; 30 if (X%a==0&&(Y-2)%a==0) return true; 31 if (Y%a==0&&(X-2)%a==0) return true; 32 if (X%a==1&&Y%a==1) return true; 33 34 return false; 35} 36int main() 37{ 38 // freopen("in.txt","r",stdin); 39 40 while (~scanf("%d%d",&X,&Y)) 41 { 42 int n; 43 scanf("%d",&n); 44 while (n--) 45 { 46 int x; 47 scanf("%d",&x); 48 // cout<<"x:"<<x<<endl; 49 if (ok(x)) puts("YES"); 50 else puts("NO"); 51 } 52 } 53return 0; 54}

seerc 2014 A Banks (暴力)

·356 words·1 min
题目链接 题意:n个数围成一圈,对于负数可以进行magic操作,也就是取反,但是会影响到左右相邻的,加上这个负数。问最少进行多少次magic操作,使得所有数都是非负。 思路:我们知道,如果一个负数想变成整数的话,只能通过magic 操作。唯一可能影响次数的就是顺序。