题目传送门:http://codeforces.com/problemset/problem/366/D
题意:有n个点m条无向边。初始你需要选择一个整数x,走第i条边的限制为Li <= x <= Ri,假设1-n的一条路径上可以选择的整数x有ans个,问你最大的ans。
分析:因为答案肯定是这些边中最优左端点到某个右端点的,所以就成了在已知左端点的情况下,维护最大的右端点。二分右端点,dfs验证是否可行即可。
#include<bits/stdc++.h> #define PI acos(-1.0) #define eps 1e-8 #define ll long long #define MEM(a, b) memset(a, b, sizeof(a)) #define pb push_back #define mp make_pair #define MII map<int,int>::iterator #define MLL map<LL,LL>::iterator #define pii pair<int,int> #define si set<int>::iterator #define sl set<LL>::iterator #define bug printf("bug-------bug-------bug\n") using namespace std; const int maxn = 1005; int Time, head[maxn], vis[maxn], eid, ans, n, m; bool success; set<int> st; struct Edge { int to, x, y, nxt; }edge[6010]; void addedge(int u, int v, int l, int r) { edge[eid].to = v; edge[eid].x = l; edge[eid].y = r; edge[eid].nxt = head[u]; head[u] = eid++; } void dfs(int u, int l, int r) { if(success) return; if(u == n) { success = true; return; } for(int i = head[u]; i != -1; i = edge[i].nxt) { int v = edge[i].to; if(vis[v] == Time || edge[i].x > l || edge[i].y < r) continue; vis[v] = Time; dfs(v, l, r); } } void solve() { ans = 0; for(si i = st.begin(); i != st.end(); i++) { int now = *i; int left = now, right = 1e6+5, mid; while(left < right) { Time++; success = false; vis[1] = Time; mid = (left + right) / 2; dfs(1, now, mid); if(success) left = mid + 1; else right = mid; } ans = max(ans, left - now); } } int main() { Time = 1; memset(vis, 0, sizeof(vis)); while(cin >> n >> m) { eid = 0; memset(head, -1, sizeof(head)); st.clear(); while(m--) { int u, v, l, r; cin >> u >> v >> l >> r; addedge(u, v, l, r); addedge(v, u, l, r); st.insert(l); st.insert(r); } solve(); if(ans == 0) printf("Nice work, Dima!\n"); else printf("%d\n",ans); } return 0; }