題目來源:HDU 4183 Pahom on Water
題意:若干個區域 每個區域有一個值 區域是圓 給出圓心和半徑
從起點(值為400.0)到終點(值為789.0)滿足走相交的圓 並且值必須遞增 然後從終點到起點 值必須遞減 此外區域只能去一次
思路:建圖 相互能走的區域連一條邊 因為只能走一次 所以拆點 如果沒有來回 只有去 那麼判斷最大流為1即可
現在還要回來 並且回來的條件和去的條件想法(一個遞增一個遞減)可以反向考慮給源點cap=2 最大流為2
#include#include #include #include #include using namespace std; const int maxn = 610; const int INF = 999999999; struct Edge { int from, to, cap, flow; Edge(){} Edge(int from, int to, int cap, int flow) : from(from), to(to), cap(cap), flow(flow){} }; struct Point { double d, x, y, r; Point(){} Point(double d, double x, double y, double r) : d(d), x(x), y(y), r(r){} }a[maxn]; int n, m, s, t; vector edges; vector G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn];void AddEdge(int from, int to, int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue Q; Q.push(s); d[s] = 0; vis[s] = 1; while(!Q.empty()) { int x = Q.front(); Q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int& i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow() { int flow = 0; while(BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } bool ok(int i, int j) { if(a[i].d >= a[j].d) return false; if((a[i].r + a[j].r)*(a[i].r + a[j].r) > (a[i].x - a[j].x)*(a[i].x - a[j].x)+(a[i].y - a[j].y)*(a[i].y - a[j].y)) return true; return false; } int main() { int T; scanf("%d", &T); while(T--) { int k; scanf("%d", &k); n = k*2; edges.clear(); for(int i = 0; i < n; i++) G[i].clear(); for(int i = 0; i < k; i++) { scanf("%lf %lf %lf %lf", &a[i].d, &a[i].x, &a[i].y, &a[i].r); if(a[i].d == 400.0) s = i; if(a[i].d == 789.0) t = i; } for(int i = 0; i < k; i++) { if(i != s && i != t) AddEdge(i<<1, i<<1|1, 1); for(int j = 0; j < i; j++) { if(ok(i, j)) { AddEdge(i<<1|1, j<<1, 1); } else if(ok(j, i)) { AddEdge(j<<1|1, i<<1, 1); } } } AddEdge(s<<1, s<<1|1, 2); s = s<<1; t = t<<1; //printf("%d %d\n", s, t); if(Maxflow() >= 2) puts("Game is VALID"); else puts("Game is NOT VALID"); } return 0; }