今天是惨遭吊打,和学长做去年的儿童节专场,只做出来A题,B题直接暴力以为会超时,dp了半天过不了,C题贪心贪错了。。。
这题的大意是有n个部件,要把他们全部破坏,破坏i就需要与i相连的那些部件的能量,比如j,k与i相连,破坏i就需要vj+vk的能量,求全部破坏需要多少能量。
我也是太年轻,直接按照每个部件拆除所需能量升序排序,然后拆能量需要最小的。
这个方法的错误在于,也许有几次拆的时候,消耗了最大的那部分能量,所以不是最优解。
贪心的思路是先拆该点能量最大的,而不是所需能量最小的,这样先把该点能量最大的拆了,后面的部件拆的时候就不会计算到最大的这个能量。(有点绕,但是想想就可以明白)
#include<iostream> #include<cstdio> #include<cctype> #include<cstdlib> #include<cmath> #include<algorithm> #include<cstring> #include<string> #include<vector> #include<queue> #include<map> #include<set> #include<sstream> #include<stack> using namespace std; #define MAX 105 typedef long long LL; const double pi=3.141592653589793; const int INF=1e9; const double inf=1e20; int edge[1005][1005]; struct vex { int w,num,degree; vex(int degree=0): degree(degree) {} } p[1005]; bool cmp(struct vex a,struct vex b) { return a.w>b.w; } int main() { int n,m; scanf("%d%d",&n,&m); memset(edge,0,sizeof(edge)); for(int i=1; i<=n; i++) { scanf("%d",&p[i].w); p[i].num=i; } for(int i=0; i<m; i++) { int x,y; scanf("%d%d",&x,&y); p[x].degree+=p[y].w; p[y].degree+=p[x].w; edge[x][y]=edge[y][x]=1; } sort(p+1,p+n+1,cmp); int sum=0; for(int i=1; i<=n; i++) { sum+=p[i].degree; int r=p[i].num; for(int j=i+1; j<=n; j++) { int s=p[j].num; if(edge[r][s]||edge[s][r]) { p[j].degree-=p[i].w; } } } printf("%d\n",sum); return 0; }