不行 我这个题我一定要单独拿出来说
本来是在做拓扑排序的练习的 然后看到这个题 一看题面 哇 好像不是很难嘛 当时绝对不会想到今天
然后 然后我看到了 第二个案例 ‘=‘ 是的 =也在矛盾的原因中 然后 噩梦开始了
明白了等于号不是摆着看的我一眼就明白了啊 并查集!很好 然鹅 很明显 猪脑子是不可能记住东西的
然后我复习了一下并查集之后又整了个学习笔记放在博客上(我这次是真的记住了!)然后!!
WAWAWAWA!!!啊啊啊啊啊啊啊!!
没事 已经大二的我已经知道了 AC才是怪事 普遍现象
开始了我为时两天4小时+的对拍之旅 对拍这个东西真的是个好东西 一次测试的数据量要少 测试的次数要多
然后 终于这个恶心叭啦叽噪的代码终于被我改的更加恶心了
你们看看还能不能抢救一下 我放弃它了!
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 10000 + 10;
int i, j;
//int g[maxn][maxn];
vector<int>g[maxn];
int c[maxn];
int in[maxn];
int f[maxn];
int n, m;
void init()
{
for (i = 0; i <= n; i++)
g[i].clear();
for (i = 0; i <= n; i++)
f[i] = i;
}
int find(int s)
{
if (s != f[s])
f[s] = find(f[s]);
return f[s];
}
void unionn(int u, int v)
{
int a = find(u);
int b = find(v);
if (a != b)
f[a] = b;
}
bool dfs(int u)
{
c[u] = -1;
int v;
for (v = 0; v < g[u].size(); v++)
{
int vv = g[u][v];
if (vv != f[vv])
vv = find(f[vv]);
if (c[vv] < 0 || find(f[vv]) == find(f[u]))return false;
if (c[vv] == 0)
if (dfs(vv) == false)return false;
}
c[u] = 1;
return true;
}
bool ss()
{
memset(c, 0, sizeof(c));
int u;
for (u = 0; u < n; u++)
{
int uu = u;
if (uu != f[uu])
{
uu = find(f[uu]);
for (int i = 0; i < g[u].size(); i++)
{
g[uu].push_back(g[u][i]);
}
}
if (c[uu] == 0)
if (dfs(uu) == false)return false;
}
return true;
}
void print()
{
for (i = 0; i < n; i++)
{
if (g[i].size())
{
for (int j = 0; j < g[i].size(); j++)
{
printf("%d -> ", i);
int v = g[i][j];
if (v == f[v])
cout << v << endl;
else
printf("%d = %d\n", v, find(f[v]));
}
}
}
}
int main()
{
while (cin >> n >> m)
{
init();
memset(in, 0, sizeof(in));
for (i = 0; i < m; i++)
{
int u, v;
char s[10], c;
scanf("%d%s%d", &u, &s, &v);
c = s[0];
if (c == '>')
{
u = find(f[u]);
v = find(f[v]);
g[u].push_back(v);
in[v]++;
}
if (c == '<')
{
u = find(f[u]);
v = find(f[v]);
g[v].push_back(u);
in[u]++;
}
if (c == '=')
{
u = find(f[u]);
v = find(f[v]);
unionn(u, v);
}
}
// print();
// system("pause");
if (ss())
{
queue<int>q;
for (i = 0; i < n; i++)
{
if (in[i] == 0)q.push(i);
}
int flag = 1;
while (q.size())
{
if (q.size() >= 2) { flag = 0; break; }
int u = q.front(); q.pop();
for (i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
in[v]--;
if (in[v] == 0)q.push(v);
}
}
if (flag)
cout << "OK" << endl;
else
cout << "UNCERTAIN" << endl;
}
else
{
cout << "CONFLICT" << endl;
}
}
//system("pause");
return 0;
}
好的 我回来了……
可能真的是思维定式 我觉得我得想想更多的判环的方法 不能拘泥于dfs判环一种 这道题其实判环的过程非常简单
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 10000 + 10;
int i, j;
//int g[maxn][maxn];
vector<int>g[maxn];
int in[maxn];
int f[maxn];
int a[maxn], b[maxn], ff[maxn];
int n, m;
int sum;
void init()
{
for (i = 0; i <= n; i++)
g[i].clear();
for (i = 0; i <= n; i++)
f[i] = i;
}
int find(int s)
{
if (s != f[s])
f[s] = find(f[s]);
return f[s];
}
bool unionn(int u, int v)
{
int a = find(u);
int b = find(v);
if (a == b)
return false;//同属一个树根
else
{
f[a] = b;//两棵树合并成一棵树?……反正就一个源头……
return true;
}
}
int main()
{
while (cin >> n >> m)
{
init();
sum = n;
memset(in, 0, sizeof(in));
for (i = 0; i < m; i++)
{
scanf("%d %c %d", &a[i], &ff[i], &b[i]);
if (ff[i]=='=')
{
if (unionn(a[i], b[i]))
sum--;
}
}
for (int i = 0; i < m; i++)
{
if (ff[i] == '=')
continue;
int x = find(a[i]);
int y = find(b[i]);
if (ff[i] == '>')
{
g[x].push_back(y);
in[y]++;
}
else
{
g[y].push_back(x);
in[x]++;
}
}
queue<int>q;
int flag = 0;
for (int i = 0; i < n; i++)
{
if (in[i] == 0 && f[i] == i)
q.push(i);
}
while (q.size())
{
if (q.size() > 1)
flag = 1;
int u = q.front(); q.pop(); sum--;
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
in[v]--;
if (in[v] == 0)
q.push(v);
}
}
if(sum>0)printf("CONFLICT\n");
else if (flag) printf("UNCERTAIN\n");
else printf("OK\n");
}
//system("pause");
return 0;
}
也不同于书本上的dfs解决拓扑排序 这里其实更接近原理一些 书本的确实抽象过了 (而且还不提拓扑排序常规操作 = =)
出一个点 点数都减一个 因为循环所以入度就不会为0 然后sum也不会为0 也就是所谓的成环……妈的 uva那道题我要用这种方法再来一遍……