HDU 4354 Missile 树的最大独立集+枚举
来源:互联网 发布:郭靖黄蓉爱情知乎 编辑:程序博客网 时间:2024/05/21 15:47
题意:
在一条直线上有C个城市,分别属于N个国家,需要炸毁至少K个国家的城市,花费的金额为两端城市的距离,国家间有M个特殊关系,有关系的两个国家中最多只能摧毁一个国家的城市,关系没有传递性,求所需要的最小花费,如果无法完成输出-1。只能炸一次且不一定要炸掉线段上所有的城市。
解题思路:最先考虑的就是用什么模型了。
假如有a个国家,有的国家之间有边相连,问选哪些国家使得选中的国家之间没有边且国家数最多。
转化一下就是 最大独立集。
最大独立集能求的貌似只有二分图和树了,
题目中说了没有环存在,所以就用树上的最大独立集来求了。(近似于贪心,不会的网上找吧)
接下来就是枚举了,
枚举一个区间,区间里 最大独立集 就是在这个区间最多能炸掉的国家数。
如果最多能炸掉的国家数>=K的话,就说明这个区间满足要求了。
不过这里枚举也有技巧,如果是暴利枚举的话,O(N^2)的复杂度肯定TLE,
好在之前有过类似思路,能转化为O(N)的复杂度。(这种思路建议保留一下,很多优化中能用)
我的city是从0到c-1存的, 最开始给个边界值 l=0,r=0;
如果在(l,r)的区间满足条件,记录答案,并把l右移一位,
否则把r右移一位,
直到r==c结束。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <stack>using namespace std;#define FOR(i,l,r) for(int i=(l);i<=(r);++i)#define REP(i,n) for(int i=0;i<(n);++i)#define DSC(i,r,l) for(int i=(r);i>=(l);--i)#define N 2110#define M 2110#define INF 2000000000struct{ int to,next;}edge[M];int head[N],ip;bool visit[N],flag[N];void add(int u,int v){ edge[ip].to=v;edge[ip].next=head[u];head[u]=ip++; edge[ip].to=u;edge[ip].next=head[v];head[v]=ip++;}struct Node{ int x; int fa; bool operator<(const Node a)const { return x<a.x; }}node[5010];struct{ int x,y;}f[1010];void dfs(int pos,int pre,int &num)//贪心法求树上的最大独立集{ visit[pos]=0; int to; for(int p=head[pos];p!=-1;p=edge[p].next) { to=edge[p].to; if(!visit[to]) continue; dfs(to,pos,num); } if(!flag[pos]) { flag[pos]=flag[pre]=1; num++; }}bool solve(int l,int r,int k,int m){ memset(visit,0,sizeof(visit)); memset(head,-1,sizeof(head)); ip=0; memset(flag,0,sizeof(flag)); int num=0; FOR(i,l,r) if(!visit[node[i].fa]) visit[node[i].fa]=1; //记录区间内存在的国家 REP(i,m) { if(visit[f[i].x] && visit[f[i].y] ) { add(f[i].x,f[i].y);//在存在的国家间建边 } } FOR(i,l,r) { if(visit[ node[i].fa ]) dfs(node[i].fa,node[i].fa,num); //求每棵树上得最大独立集 } if(num>=k) return 1; return 0;}int aaaa(int c,int n,int k,int m){ if(!solve(0,c-1,k,m)) return -1; if(k<=1) return 0;//如果K<=1 ,随意炸掉一个城市就够了 int l=0,r=0; int ans=2e9; while(r<c) { if(solve(l,r,k,m)) { ans=min(ans,node[r].x-node[l].x); l++; } else r++; } return ans;}int main(){ int cas,cas1=1; cin>>cas; int c,n,k,m; while(cas--) { cin>>c>>n>>k>>m; REP(i,c) scanf("%d%d",&node[i].x,&node[i].fa); REP(i,m) scanf("%d%d",&f[i].x,&f[i].y); sort(node,node+c);//对原先的city按坐标排一次序 printf("Case #%d: %d\n",cas1++,aaaa(c,n,k,m)); } return 0;}
- HDU 4354 Missile 树的最大独立集+枚举
- 【最大独立集】HDU
- hdu 2412 基础树形DP 树的最大独立集
- 树的最大独立集
- 树的最大独立集
- 树的最大独立集
- 树的最大独立集
- 树的最大独立集
- hdu 1068(最大独立集)
- HDU-1068 最大独立集
- hdu 2768 最大独立集
- hdu 1068 (最大独立集)
- HDU 1068 最大独立集
- HDU 5556 (最大独立集)
- hdu 1068 最大独立集
- hdu 5556 Land of Farms【思维+暴力枚举+最大独立集】好题!
- hdu 4354 Missile(中心区间枚举+树形DP判断,5级)
- hdu Girls and Boys(二分图的最大独立集)
- 64位时间戳实现
- 游戏数据的捕捉(郁金香学习笔记)
- 删除可执行文件的图标
- hdu2767Proving Equivalences(强连通+缩点)
- 最小生成树
- HDU 4354 Missile 树的最大独立集+枚举
- D3D混合纹理
- js 当中的预编译
- 离散化 和多维线段树
- 嵌入式开发基础----register和volatile关键字
- Oracle sql语句
- C可变参数的函数
- nbutoj1482
- C++的namespace详解1