是否有环往往很大程度上影响着一道关于图的问题。
描述 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