Description:
给出一个n节点m边的有向图,每条边上有一个权值c,现在有一个值为ans,假定仅可以把图中所有的权值小于ans的边自由反向,可以使得整个图无环。求最小的ans,以及相应的反向边有哪些。
Input:
n,m
ui,vi,ci(i=1,2,.....m)
Output:
ans 反向边的数量t
idxi(反向边的编号 i=1..t)
Analysis:
一般遇到这样复杂的优化问题,总是会想到二分搜索,试探假如已经知道了答案,能否较为方便的判断可行性。这一题可以用拓扑排序判断,对于边权大于ans的子图进行拓扑排序,若存在环则ans肯定不行,因为这些边无法改变。若可以进行拓扑排序,就可以的到一个拓扑序,则只要对剩下的边权小于等于ans的边顺着拓扑序的方向就能使得整个图无环.
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<unordered_set>
#include<ctime>
#include<cstring>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1 << 30;
const int maxn = 100005;
const int MOD = 1e9+7;
const double eps = 1e-6;
const double pi = acos(-1);
struct Edge {
int id,to;
int c;
Edge(int id,int to,int c):id(id),to(to),c(c){}
Edge(){}
bool operator < (const Edge & rhs)const {
return c < rhs.c;
}
};
int n, m;
vector<Edge> G[maxn];
void Topological_sort(int x,vector<int> & order) {
order.clear();
vector<int> in_deg(n+1, 0);
_rep(i,1,n)
for (auto e : G[i]) {
if (e.c <= x) continue;
in_deg[e.to]++;
}
_rep(i, 1, n)if (in_deg[i] == 0) {
order.push_back(i);
}
int current = 0;
while (current < order.size()) {
int u = order[current++];
for (auto e : G[u]) {
if (e.c <= x) continue;
if (--in_deg[e.to] == 0) {
order.push_back(e.to);
}
}
}
}
bool Judge(int x,vector<int> & order) {
order.clear();
Topological_sort(x,order);
return order.size() == n;
}
int main()
{
//freopen("C:\\Users\\admin\\Desktop\\in.txt", "r", stdin);
//freopen("C:\\Users\\admin\\Desktop\\out.txt", "w", stdout);
ios_base::sync_with_stdio(0);//用这个
cin.tie(0); //就能防止cin超时orz
while (cin >> n >> m) {
_rep(i, 1, n) G[i].clear();
int ans = 0;
_rep(i,1,m) {
int u, v, c;
cin >> u >> v >> c;
G[u].push_back(Edge(i, v, c));
ans = max(ans, c);
}
vector<int> order;
int L = 0, R = ans;
while (L <= R) {
int mid = L + (R - L) / 2;
if (Judge(mid,order)) {
ans = mid;
R = mid - 1;
}
else L = mid + 1;
}
Topological_sort(ans, order);
vector<int> location(n + 1);
for (int i = 0; i < n; ++i) {
location[order[i]] = i;
}
vector<Edge> p;
for(int i=1;i<=n;++i)
for (auto e : G[i]) {
if (location[e.to] < location[i])
p.push_back(e);
}
cout << ans << " " << p.size() << endl;
for (auto it : p) cout << it.id << " ";
cout << endl;
}
return 0;
}