是否有环往往很大程度上影响着一道关于图的问题。
描述 Description(Time Limit: 1s ; Memory Limit 128MB)
有n个炸弹,有些炸弹牵了一根单向引线(也就是说引线只有在这一端能被炸弹点燃),只要引爆了这个炸弹,用引线连接的下一个炸弹也会爆炸。每个炸弹还有个得分,当这个炸弹被引爆后就能得到相应得分。
现在要你引爆k个炸弹,使得分最大。
输入格式 InputFormat
第1行两个整数n、k。
接下来n行每行两个整数a[i]、b[i]。a[i]表示这个炸弹用引线连接的下一个炸弹,如果a[i]为0,则表示这个炸弹没连接引线。b[i]表示这个炸弹的得分。
输出格式 OutputFormat
仅一个数,表示最大得分。
样例输入 SampleInput
8 2
0 1
1 1
2 100
2 100
0 1
5 1
6 2
6 2
样例输出 SampleOutput
202
数据范围和注释 Hint
1≤b[i]≤1000000
对于30%的数据,n≤1000 k≤30
对于60%的数据,n≤50000 k≤100
对于100%的数据,n≤200000 k≤500
这个题有没有环呢?
我们的数据里没有。
因此就可以预处理出所有 叶子节点 的最大连锁爆炸值,然后降序排序;
接着按顺序对每个连锁爆炸进行处理:如果它的连锁爆炸过程中有之前已经爆炸过的炸弹,就减掉这颗炸弹的爆炸值;否则把这颗炸弹标记为已爆炸。
然后再排一遍序,从大到小记录k个值的和,输出即可。(要开long long 啊)
<span style="font-size:18px;"><strong>#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<queue> using namespace std; int n,k; struct zhadan { int w,next; }b[200010]; struct defen { int i; long long fen; friend bool operator < (defen a,defen b) { return a.fen>b.fen; } }s[200010]; long long dfs(int x) { if(x==0) return 0; if(s[x].fen>0) return s[x].fen; int ne=b[x].next; return s[x].fen=b[x].w+dfs(ne); } bool vis[200010]; int main() { freopen("bomb.in","r",stdin); freopen("bomb.out","w",stdout); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%d%d",&b[i].next,&b[i].w); s[i].i=i; } for(int i=1;i<=n;i++) dfs(i); sort(s+1,s+n+1); int u,ne; for(int i=1;i<=n;i++) { u=s[i].i; ne=b[u].next; if(vis[u]) s[i].fen-=b[u].w; vis[u]=1; while(ne!=0) { if(vis[ne]) s[i].fen-=b[ne].w; vis[ne]=1; ne=b[ne].next; } } sort(s+1,s+n+1); long long ans=0; for(int i=1;i<=k;i++) ans+=s[i].fen; printf("%I64d\n",ans); return 0; }</strong></span>当然,如果有环的话就要涉及到缩点了(喜(sang)闻(xin)乐(bing)见(kuang))。
<span style="font-size:18px;color:#009900;"><strong style="background-color: rgb(255, 102, 102);">#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <queue> using namespace std; //注意一个炸弹可能被多个导线引爆,但是最多引爆下一个炸弹,这个可能很关键 //那么如果倒过来建图,就是一个森林 //建图的时候似乎可以缩边优化 //如果有环,直接缩点,并且缩点完了一定是根 //贪心一定是对的,每次选一条树上的最长路,Bomb! //Global Variables int n,k; int w[200010]; //End Global Variables template<typename _Tp> //Map namespace MAP{ int h[200010]; struct edge { int v,next; }e[200010]; int ecnt = -1; inline void adde(int u,int v) { ecnt++; e[ecnt].v = v; e[ecnt].next = h[u]; h[u] = ecnt; } inline void reset() { memset(h,-1,sizeof(h)); ecnt = -1; } } //End Map //Tree namespace TREE{ using namespace MAP; //Variables //左儿子右兄弟 struct node { int num; int l,r,f; long long maxpathsum; int maxpathson; long long w; node(int num = -1,int f = -1,long long w = 0,int l = -1,int r = -1):num(num),f(f),w(w),l(l),r(r){} int Addson(long long w); void Setson(int n); long long maxpath(); void Del(); void _DFS(); }T[200010]; int Tcnt = 0; int node::Addson(long long w) { T[Tcnt] = node(Tcnt,this -> num,w,-1,-1); this -> Setson(Tcnt); return Tcnt++; } void node::Setson(int n) { T[n].f = this -> num; if(this -> l == -1) { this -> l = n; }else{ int i = this -> l; for(;T[i].r != -1;i = T[i].r); T[i].r = n; } } long long node::maxpath() { long long rv = 0; this -> maxpathson = -1; if(this -> l == -1) { // PRINT("maxpath[%d] = %lld\n",this -> num,this -> w); return this -> maxpathsum = this -> w; }else{ for(int i = this -> l;i != -1;i = T[i].r) { T[i].maxpath(); if(T[i].maxpathsum > rv) { rv = T[i].maxpathsum; this -> maxpathson = i; } } //PRINT("maxpath[%d] = %lld\n",this -> num,rv + this -> w); return this -> maxpathsum = (rv + this -> w); } } struct gr { bool operator()(int & _x,int & _y) const { return T[_x].maxpathsum < T[_y].maxpathsum; } }; priority_queue<int,vector<int>,gr>roots; void node::Del() { for(int i =this -> l;i != -1;i = T[i].r) { if(i == this->maxpathson) { T[i].Del(); }else{ roots.push(i); } } } void node::_DFS() { //PRINT("%d\n",this -> num); for(int i = this -> l;i != -1;i = T[i].r) { T[i]._DFS(); } //PRINT("~%d\n",this -> num); } //End Variables //Functions //建树 int vis[200010]; int cn[200010]; int isroot[200010]; void DFS(int u,int vn,int & is_circle) { //PRINT("%d %d\n",u,cn[u]); vis[u] = vn; int sub_circle = 0; int thi_circle = 0; for(int i = h[u];i != -1;i = e[i].next) { int v = e[i].v; if(vis[v]) { if(vis[v] == vn) { //成环了 thi_circle = 1; }else{ //连上一个访问过的子树,则子树的根一定不是缩出来的点 T[cn[u]].Setson(cn[v]); isroot[cn[v]] = 0; } }else{ cn[v] = T[cn[u]].Addson(w[v]); isroot[cn[v]] = 0; DFS(v,vn,sub_circle); if(sub_circle) { if(T[cn[u]].l == cn[v]) { T[cn[u]].l = T[cn[v]].r; }else{ for(int i = T[cn[u]].l;i != -1;i = T[i].r) { if(T[i].r == cn[v]) { T[i].r = T[cn[v]].r; break; } } } } } } if((sub_circle || thi_circle) && isroot[cn[u]] == 0) { //PRINT("merge %d\n",u); is_circle = 1; //Merge to father int f = T[cn[u]].f; if(T[cn[u]].l != -1) { T[f].Setson(T[cn[u]].l); for(int i = T[cn[u]].l;i != -1;i = T[i].r) { T[i].f = f; } } T[f].w += T[cn[u]].w; } } void Build() { memset(vis,0,sizeof(vis)); for(int ii = 0;ii < 200010;ii++){ isroot[ii] = 1; } for(int i = 1;i <= n;i++)if(!vis[i]) { int temp; cn[i] = Tcnt++; T[cn[i]] = node(cn[i],-1,w[i]); DFS(i,i,temp); } for(int i = 0;i < Tcnt;i++)if(isroot[i]) { T[i].maxpath(); //T[i]._DFS(); roots.push(i); } } //初始化计算 void Init() { return; } //一次贪心 long long Do() { int u = roots.top();roots.pop(); T[u].Del(); //PRINT("choose %d %lld\n",u,T[u].maxpathsum); return T[u].maxpathsum; Init(); } } //End Tree //Main Structure inline void ir() { freopen("bomb.in","r",stdin); freopen("bomb.out","w",stdout); scanf("%d%d",&n,&k); MAP::reset(); int a; for(int i = 1;i <= n;i++) { scanf("%d%d",&a,&w[i]); //反向加边 MAP::adde(a,i); } } int main() { ir(); TREE::Build(); TREE::Init(); long long ans = 0; for(int i = 0;i <k;i++) { ans += TREE::Do(); } cout << ans << '\n'; return 0; }</strong></span><span style="font-size:14px;"> </span>
原文地址:http://blog.csdn.net/u011500508/article/details/40481345