【HDU - 5934】Bomb (强连通分量Tarjan + 缩点)
題干:
There are?NN?bombs needing exploding.?
Each bomb has three attributes: exploding radius?riri, position?(xi,yi)(xi,yi)?and lighting-cost?cici?which means you need to pay?cici?cost making it explode.?
If a un-lighting bomb is in or on the border the exploding area of another exploding one, the un-lighting bomb also will explode.?
Now you know the attributes of all bombs, please use the?minimum?cost to explode all bombs.
Input
First line contains an integer?TT, which indicates the number of test cases.?
Every test case begins with an integers?NN, which indicates the numbers of bombs.?
In the following?NN?lines, the ith line contains four intergers?xixi,?yiyi,?riri?and?cici, indicating the coordinate of ith bomb is?(xi,yi)(xi,yi), exploding radius is?riri?and lighting-cost is?cici.?
Limits?
-?1≤T≤201≤T≤20?
-?1≤N≤10001≤N≤1000?
-??108≤xi,yi,ri≤108?108≤xi,yi,ri≤108?
-?1≤ci≤1041≤ci≤104
Output
For every test case, you should output?'Case #x: y', where?x?indicates the case number and counts from?1?and?y?is the minimum cost.
Sample Input
1 5 0 0 1 5 1 1 1 6 0 1 1 7 3 0 2 10 5 0 1 4Sample Output
Case #1: 15題目大意:
現有N顆炸彈急需引爆。每顆炸彈有三個屬性:爆炸半徑ri,炸彈位置(xi, yi),還有起爆費用ci,即你需要花費ci才能引爆這個炸彈。如果一顆未引爆的炸彈在另一顆炸彈的爆炸半徑邊緣或者其中,則會被連鎖引爆。此時你已得知所有炸彈的屬性,用最小的花費引爆所有炸彈吧。
解題報告:
? ?強連通分量 + 縮點。先跑一遍Tarjan把所有可以互相引爆的炸彈縮成一個點,也就是說這些只需要看這些小集合之間的關系,這些小集合之間由于不存在互相引爆的情況,所以構成一個DAG圖,那么我們引爆所有入度為0的集合就可以了,對于集合內部,我們選擇那個爆炸燃燒最小的花費就行了。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 2e4 + 5;struct Point {ll x, y, r, c; } p[MAX]; struct Edge {int fr,to,ne; } e[2000010]; int head[MAX],id,cnt,tot,index; int n; int DFN[MAX],vis[MAX],stk[MAX],LOW[MAX],bel[MAX],in[MAX]; bool ok(int u, int v) {double res = sqrt(((p[u].x - p[v].x) * (p[u].x - p[v].x) + (p[u].y - p[v].y) * (p[u].y - p[v].y)));if(res <= p[u].r) return 1;return 0; } void add(int u, int v) {e[++tot].to = v;e[tot].ne = head[u];head[u] = tot; } void Tarjan(int x) {DFN[x] = LOW[x] = ++id;stk[++index] = x;vis[x] = 1;for(int i = head[x]; i!=-1; i = e[i].ne) {if(!DFN[e[i].to]) {Tarjan(e[i].to);LOW[x] = min(LOW[x],LOW[e[i].to]);}else if(vis[e[i].to]) {LOW[x] = min(LOW[x],DFN[e[i].to]);}}if(LOW[x] == DFN[x]) {cnt++;while(1) {int tmp = stk[index];index--;bel[tmp] = cnt;vis[tmp]=0;if(tmp == x) break;}}} void init() {for(int i = 1; i<=n; i++) {head[i]=-1;DFN[i]=LOW[i]=bel[i]=vis[i]=in[i]=0;}cnt=tot=id=index=0; } int main() {int t,iCase=0;cin>>t;while(t--) {scanf("%d",&n);init();for(int i = 1; i <= n; i++) scanf("%lld%lld%lld%lld", &p[i].x, &p[i].y, &p[i].r, &p[i].c);for(int i = 1; i <= n; i++) {for(int j = 1; j <= n; j++) {if(i == j) continue;if(ok(i, j)) add(i, j);}}for(int i = 1; i <= n; i++) if(!DFN[i]) Tarjan(i); for(int i = 1; i<=n; i++) {for(int j = head[i]; j!=-1; j = e[j].ne) {int u = i,v = e[j].to;if(bel[u]!=bel[v]) {in[bel[v]]++;}}}ll ans = 0;for(int i = 1; i<=cnt; i++) {if(in[i]!=0) continue;ll minn = 0x3f3f3f3f;for(int j = 1; j<=n; j++) {if(bel[j] == i) {minn = min(minn,p[j].c);}}ans += minn;}printf("Case #%d: %d\n", ++iCase, ans);}return 0 ; }?
總結
以上是生活随笔為你收集整理的【HDU - 5934】Bomb (强连通分量Tarjan + 缩点)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最近可转债接连破发,想赚钱掌握两个方法
- 下一篇: 浦发信用卡审核要多久 审核通过花两天制卡