HDU 4354 Missile 树的最大独立集+枚举
2013-07-20 10:16
309 查看
题意:
在一条直线上有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结束。
在一条直线上有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 2000000000 struct { int to,next; }edge[M]; int head ,ip; bool visit ,flag ; 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(中心区间枚举+树形DP判断,5级)
- hdu 4354 Missile(中心区间枚举+树形DP判断,5级)
- hdu 5556 Land of Farms【思维+暴力枚举+最大独立集】好题!
- HDU - 5556 Land of Farms 枚举 + 无向二分图最大独立集
- hdu 3081 【二分匹配+并查集+删边||最大路+并查集+二分枚举】
- hdu 1068(最大独立集)
- hdu 2458 Kindergarten (最大独立集)
- hdu 1068 girls and boys(二分图求最大独立集)
- poj 1466 && hdu 1068Girls and Boys(最大独立集)
- 【最大独立集 && 无墙 && 无向图】HDU - 1281 棋盘游戏
- hdu 2768 Cat vs. Dog 最大独立集
- hdu 1068 Girls and Boys(最大独立集模板)
- hdu 2236 无题II(二分法,枚举,二分图最大匹配)
- 二分图带权最大独立集 网络流解决 hdu 1569
- 【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- hdu 4309(最大流+枚举状态)
- hdu 3657(最大点权独立集)
- 【hdu 2412 Party at Hali-Bula 】(树形dp求最大独立集+判断唯一性)
- HDU 4081 Qin Shi Huang's National Road System(最小生成树,记录圈中最大边后暴力枚举)
- HDU 1569 方格取数(2)(最大点权独立集)