版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014046022/article/details/81636993
描述
有N个整数A1, A2, … AN,现在我们知道M条关于这N个整数的信息。每条信息是:
Ai < Aj 或者 Ai = Aj
小Hi希望你能从第一条信息开始依次逐条处理这些信息。一旦能推断出A1和AN的大小关系就立即停止。
输出在处理第几条时第一次推断出A1和AN的关系。如果处理完全部M条信息还是不知道A1和AN的大小关系,输出-1。
保证M条信息是没有矛盾的。
输入
第一行包含两个整数N和M。
以下M行每行包含一条信息Ai < Aj 或者 Ai = Aj。
对于30%的数据,1 ≤ N ≤ 1000, 1 ≤ M ≤ 10000
对于100%的数据,1 ≤ N ≤ 100000, 1 ≤ N ≤ 1000000
输出
一个整数表示答案。
样例输入
5 8
A1 < A3
A3 < A2
A3 < A4
A5 < A2
A1 < A4
A1 < A2
A5 < A1
A5 < A3
样例输出
7
思路:
二分枚举边,假设前k条边可以得出答案 那么前k+1条边也必定会得到答案 时间复杂度
发现 dfs的时候 用 if (visit[x]) continue 比用 if(!visit[x]) { dfs (x) ;} 要快啊!!!!!
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
vector<int>E[maxn];
int visit[maxn];
int x[maxn];
int y[maxn];
int op[maxn];
int n,m;
bool dfs(int a, int des)
{
visit[a] = 1;
if (a == des) return true;
for (int i = 0; i < (int)E[a].size(); ++i) {
int tmp = E[a][i];
if (!visit[tmp]) {
if (dfs(tmp,des)) return true;
}
}
return false;
}
bool judge(int mid)
{
for (int i = 1; i <= n; ++i) E[i].clear();
for (int i = 1; i <= mid; ++i) {
if (op[i]) {
E[x[i]].push_back(y[i]);
E[y[i]].push_back(x[i]);
}
else
E[x[i]].push_back(y[i]);
}
memset(visit,0,sizeof(visit));
if (dfs(1,n)) return true;
memset(visit,0,sizeof(visit));
if (dfs(n,1)) return true;
return false;
}
void solve(int n,int m)
{
int res = -1;
int l = 1, r = m;
while(l <= r) {
int mid = (l+r)/2;
if (judge(mid)) {
r = mid-1;
res = mid;
}
else
l = mid+1;
}
cout << res << endl;
}
int main()
{
string u,s,v;
cin >> n >> m;
for (int i = 0; i < m; ++i) {
cin >> u >> s >> v;
u = u.substr(1,u.length()-1);
v = v.substr(1,v.length()-1);
int a = std::stoi(u);
int b = std::stoi(v);
x[i+1] = a;
y[i+1] = b;
if (s == "=")
op[i+1] = 1;
else
op[i+1] = 0;
}
solve(n,m);
return 0;
}