题目:
题目1:
题目描述:
用小于号"<"来定义两元素之间的关系,并于一个没有重复元素的有序上升序列 从小到大地排列这些元素。
比如说,序列A,B,C,D意味着A 在这个问题里,我们会给你一组形如"A
输入
输入有多组数据。
每一组数据由其第一行的2个正整数n,m开始。
第一个正整数n代表有n个元素需要排序(2<=n<=26),这些元素一定是按照字母表顺序,从第一个字母(A)开始的n个大写字母。
第二个正整数m代表有m个关系将会在这组数据中被给出。
接下来有m行输入,每一行输入包含3个字符:一个大写字母,一个"<"符号,另一个大写字母。
所有输入的字母不会超出n规定下的,字母表中的字母范围。
当输入的n=m=0时,代表输入结束。
输出
对于每一组数据,输出有一行。输出必须也必定是以下三种情况之一:
Sorted sequence determined after X relations: YYYY.
[友情翻译:有序序列在给出X个条件后可以成立: YYYY.]
Sorted sequence cannot be determined.
[翻译:无法建立有序序列]
Inconsistency found after X relations.
[翻译:在给出X个关系后出现矛盾]
X是一个整数。
YYYY是当前条件下的有序数列,之间没有分隔符与空格。
样例输入
4 6
A A
A B 26 1
A
样例输出
Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.
Sorted sequence cannot be determined.
思路:
给定一组字母的大小关系,要你判断是否在某一次读入后,能够判断
1.该字母序列有序,并依次输出;
2.该序列不能判断是否有序;
3.该序列字母次序之间有矛盾,即有环存在。
而这三种形式的判断应该遵循这样的顺序:先判断是否有环(3),再判断是否有序(1),最后才能判断是否能得出结果(2)。
注意:对于(2)必须遍历完整个图!!,而(1)和(3)一旦得出结果,对后面的输入就不用做处理了。
AC代码:
#include
using namespace std;
const int N = 30;
int Map[N][N],indegree[N],temp[N],Stack[N];
char s[N];
int n;
int tuopu()
{
int i,j;
int num;
int tail = -1,now,flag = 1;
for(i =0; i < n; i ++)//将每个点的入度先用临时数组存起来,因为一会要修改
{
temp[i] = indegree[i];
}
for(i = 0; i < n; i ++)//把每个入度为0的点删除,遍历n个点(如果能得出结果的话)
{
num = 0;//入度为0的点的个数
for(j = 0; j < n; j ++)
{
if(temp[j] == 0)
{
now = j;//标记这个入度为0的点
num ++;
}
}
if(num == 0) return -1;//没有入度为0的点,证明存在环,关系矛盾,直接返回,得出结果
if(num > 1) flag = 0;//入度为0的点的个数大于1,也得不出关系,但现在不能直接返回,因为当前也有可能存在环,只是还没判断到,要等大循环结束
Stack[++tail] = now;//当前只有一个入度为0的点,有可能能得出结果,先把当前的信息存起来
temp[now] = -1;//此入度为0的点标记为-1,避免再次判断
for(j = 0; j < n; j ++)//把此点连接的点入度减1
{
if(Map[now][j]==1) temp[j] --;
}
}
return flag;
}
int main()
{
int i,j;
int m,a,b;
int flag,sign;
while(cin >> n >> m)
{
sign = 0;
memset(Map,0,sizeof Map );
memset(indegree,0,sizeof indegree );
if(n == 0 && m == 0) return 0;
for(i = 0; i < m; i ++)
{
cin >> s;
if(sign == 1) continue;
a = s[0] -'A';
b = s[2] - 'A';
Map[a][b] = 1;//邻接矩阵存边
indegree[b] ++;//b的入度加一
flag =tuopu();//m每给出一条信息,就重新判断,判断当前的已知信息能不能得出结果
if(flag == -1)//关系矛盾
{
cout << "Inconsistency found after "<< i + 1 << " relations." << endl;
sign = 1;//已经得出了结果
}
else if(flag == 1)//得出关系
{
cout << "Sorted sequence determined after "<< i + 1 << " relations: ";
for(j = 0; j < n; j++)
{
printf("%c",Stack[j]+'A');
}
printf(".\n");
sign = 1;
}
}
if(!sign)//当前所给信息不足以得出关系
{
cout << "Sorted sequence cannot be determined." << endl;
}
}
return 0;
}
题目2:
题目描述:
给定一张无向图,求图中一个至少包含3个点的环,环上的节点不重复,并且环上的边的长度之和最小。
该问题称为无向图的最小环问题。你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。
输入格式:
第一行包含两个整数N和M,表示无向图有N个点,M条边。
接下来M行,每行包含三个整数u,v,l,表示点u和点v之间有一条边,边长为l。
输出格式:
输出占一行,包含最小环的所有节点(按顺序输出),如果不存在则输出’No solution.’。
数据范围:
1≤N≤100 ,
1≤M≤10000,
1≤l<500
样例:
输入样例:
5 7
1 4 1
1 3 300
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20
输出样例:
1 3 5 2
思路:
1.本题的思路就是考虑最小环里面节点编号最大的节点为k,且环里面与k相连的两个点为i,j,环的长度为g[i][k]+g[k][j]+d[j][i];
2.则d[j][i]则表示j到i且经过的节点编号小于k,因为在环中k就是最大的,只能经过小于k的节点了;
3.则这与floyd中k次循环开始前的d[i][j]意义相同;
4.那就不妨在floyd的第一重循环就求一下以k为最大节点编号的环的长度,注意这里的k必须与节点的意义一样:0-n-1或1-n;
AC代码:
#include
using namespace std;
typedef long long ll;
const int N = 110,INF = 0x3f3f3f3f;
int d[N][N],g[N][N];
int pos[N][N];
int path[N],cnt;
void get_path(int i,int j)
{
if(pos[i][j] == 0) return;//表示pos没有被更新过,即i,j间直达不需要借助节点就最短;
int k = pos[i][j];
get_path(i,k);
path[cnt ++] = k;
get_path(k,j);
}
int main()
{
int i,j,k;
int n,m;
cin >> n >> m;
memset(g, 0x3f, sizeof g);
for(i = 1 ; i <= n ; i ++) g[i][i] = 0;
int a,b,c;
while(m --)
{
cin >> a >> b >> c;
g[a][b] = g[b][a] = min(g[a][b], c);
}
memcpy(d, g, sizeof g);
ll res=INF;
for(k = 1 ; k <= n ; k ++)//每一次开始本次floyd时,d[i][j]的实际意义是从i到j经过的节点编号最大就是k-1
{
for(i = 1 ; i < k ; i ++)//注意i和j的枚举范围
{
for(j = i + 1 ; j < k ; j ++)
{
if(g[i][k]+g[k][j]+d[j][i] < res)
{
res = g[i][k] + g[k][j] + d[j][i];
//记录最小环
cnt=0;
path[cnt ++] = k;
path[cnt ++] = i;
get_path(i,j);
path[cnt ++] = j;
}
}
}
for(i = 1 ; i <= n ; i ++)
{
for(j = 1 ; j <= n ; j ++)
{
if(d[i][k] + d[k][j] < d[i][j])
{
d[i][j] = d[i][k] + d[k][j];
pos[i][j] = k;//代表i到j的最短距离要紧过节点编号不超过k的若干点,且一定经过k点
}
}
}
}
if(res == INF) cout << "No solution." << endl;
else
{
for(i = 0 ; i < cnt ; i ++) cout << path[i]<<" ";
}
return 0;
}