HDU 5423 Rikka with Graph (图论)
【题目链接】:click here~~
【题意】:
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的: 勇太有一张n个点m条边的无向图,每一条边的长度都是1。现在他想再在这张图上连上一条连接两个不同顶点边,使得1号点到n号点的最短路尽可能的短。现在他想要知道最短路最短是多少,以及再保证最短路最短的情况下,他有多少种连边的方案。 当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
数据组数不超过100组。每组数据的第一行两个整数n,m(2≤n≤100,0≤m≤100)。 接下来m行。每行两个整数u,v(1≤u,v≤n),代表原图中的一条无向边。注意可能有自环和重边。
对于每一组数据输出一行两个整数:最短路最短是多少以及加边的方案数。
2 1 1 2
1 1
你只能连上1 2这条边。【思路】:
如果连上1-n的边,最短距离就是1。所以所有情况下最短距离都是1。
考虑方案数,如果本来没有1-n的边,那么只能连1-n,方案数为1。否则怎么连都可以,方案数是2n(n−1)。
那么答案就明显了,代码:#include <bits/stdc++.h> using namespace std; int main() { int n,m,u,v; while(scanf("%d%d",&n,&m)!=EOF) { int ok=1; while(m--) { scanf("%d%d",&u,&v); if((u==1&&v==n)||(u==n&&v==1)) ok=0; } if(ok) puts("1 1"); else printf("%d %d\n",1,((n-1)*n)/2); } return 0; }
HDU 5424 Rikka with Graph II
【题目链接】:click here~~
【题意】:
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的: 勇太有一张n个点n条边的无向图,现在他想要知道这张图是否存在一条哈密顿路径。 当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
数据组数不超过100组。每组数据的第一行一个整数n(1≤n≤1000)。 接下来n行。每行两个整数u,v(1≤u,v≤n),代表给定图上的一条边。
对于每一组数据,如果图中存在一条哈密顿路径,输出"YES"否则输出"NO"。
4 1 1 1 2 2 3 2 4 3 1 2 2 3 3 1
NO YES
第二组数据的一条哈密顿路径是1->2->3 如果你不知道哈密顿路径是什么,戳这里(https://en.wikipedia.org/wiki/Hamiltonian_path).【思路】:
如果图是联通的,可以发现如果存在哈密顿路径,一定有一条哈密顿路径的一端是度数最小的点,从哪个点开始直接DFS搜索哈密顿路径复杂度是 O(n)的。要注意先判掉图不连通的情况。
题解貌似说的还是不太清楚,博主查找其他资料,力图用自己的语言尽可能详细的讲明白:
哈密顿图(Hamiltonian path,或Traceable path)是一个无向图,在一个有多个城市的地图网络中,寻找一条从给定的起点到给定的终点沿 途恰好经过所有其他城市一次的路径。这个问题和著名的七桥问题的不同之处在于,过桥只需要确定起点,而不用确定终点。哈密顿问题寻找一条从给定的起点到给定的终点沿 途恰好经过所有其他城市一次的路径。
那么如果存在哈密顿路,此时路径中含有n-1条边,剩下的那一条要么是自环(这里不予考虑,因为哈密顿路必然不经过),要么连接任意两个点。不考虑自环,此时图中的点度数为1的个数必然不超过2个,有如下三种情况:
1、剩下的那条边连接起点和终点,此时所有点度数都是2,可以从任意一个顶点开始进行DFS,看能否找到哈密顿路
2、剩下的那条边连接除起点和终点外的任意两个点,此时起点和终点度数为1,任选1个开始进行DFS。
3、剩下的那条边连接起点和除终点的任意一个点,或者连接终点与除起点外的任意一个点,此时图中仅有1个点度数为1,从该点开始进行DFS即可。
代码思路:if(不连通)//记录自环和重边数即可,不用遍历 输出NO
if(没有环)
{
if(度=1的点超过2个) NO
else YES
}
else
{
if(度=1的点超过2个) NO
else if(度=1的点少于2个) YES
else
{
从度为1 的点开始搜索,搜索没有访问的点,同时判断是否满足条件
}
}
}
代码:
#include <bits/stdc++.h> using namespace std; const int N=1005; vector <int >g[N]; bool vis[N]; int dg[N]; int cnt; int n,u,v; bool ok; void dfs(int u,int cur) { if(cur==n) { ok=true; return ; } if(ok) return ; for(int i=0; i<g[u].size(); ++i) { int v=g[u][i]; if(vis[v]) continue; vis[v]=true; dfs(v,cur+1); vis[v]=false; } } int main() { while(scanf("%d",&n)!=EOF) { memset(vis,0,sizeof(vis)); memset(dg,0,sizeof(dg)); for(int i=1; i<=n; ++i) g[i].clear(); for(int i=1; i<=n; ++i) { scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); dg[u]++; dg[v]++; } ok=true; cnt=0; for(int i=1; i<=n; ++i) { if(dg[i]==0) ok=false; else if(dg[i]==1) cnt++; } if(!ok||cnt>2) { puts("NO"); continue; } if(cnt==0) puts("YES"); else { ok=false; for(int i=1; i<=n; ++i) { if(dg[i]==1) { vis[i]=true; dfs(i,1); if(ok) break; } } if(ok) puts("YES"); else puts("NO"); } } return 0; }