首页 > 代码库 > HDU 4354

HDU 4354

思路是在看电视时突然想到的。枚举区间,然后按树形DP来选择最大值看是否满足条件。但枚举区间时的方法低效,看了题解,说枚举区间可以设两个指针逐步移动,

开始 l = r = 1, 记录已经出现的国家。

判断是否满足条件。

如果满足,更新答案,更新区间出现的国家,l++, 一直到不满足。

如果不满足,更新区间出现的国家,r++, 一直到满足。

但我写了好久,呃,没正确。。。。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int C,N,K,M,cnt,tot;struct City{	int x,belong;};City cities[5050];int head[2050];int dp[2050][2];bool vis[2050];struct node{	int u,v;	int next;}edge[6500];bool cmp(City a,City b){	if(a.x<b.x) return true;	return false;}int belong[2050];void addedge(int u,int v){	edge[tot].u=u;	edge[tot].v=v;	edge[tot].next=head[u];	head[u]=tot++;}void dfs(int u,int f){	dp[u][0]=0;dp[u][1]=1;	vis[u]=true;	for(int ei=head[u];ei!=-1;ei=edge[ei].next){		if(f!=edge[ei].v&&belong[edge[ei].v]>0&&!vis[edge[ei].v	]){			dfs(edge[ei].v,u);			dp[u][1]+=dp[edge[ei].v][0];			dp[u][0]+=max(dp[edge[ei].v][0],dp[edge[ei].v][1]);		}	}}bool judge(){	int ans=0;	memset(vis,false,sizeof(vis));	for(int i=1;i<=N;i++){		if(!vis[i]&&belong[i]>0){			dfs(i,0);			ans+=max(dp[i][0],dp[i][1]);		}	}	if(ans>=K) return true;	else return false;}int main(){	int T,t=0,u,v,l,r;	scanf("%d",&T);	while(++t<=T){		scanf("%d%d%d%d",&C,&N,&K,&M);		cnt=tot=0;		for(int i=1;i<=C;i++){			scanf("%d%d",&cities[i].x,&cities[i].belong);		}		memset(head,-1,sizeof(head));		sort(cities+1,cities+1+C,cmp);		for(int i=1;i<=M;i++){			scanf("%d%d",&u,&v);			addedge(u,v);			addedge(v,u);		}		cnt=l=r=1;		int ans=-1;		memset(belong,0,sizeof(belong));		while(r<=C){			if(cnt>=K && judge()){			     if(ans==-1||cities[r].x - cities[l].x<ans)    	       	 ans=cities[r].x - cities[l].x;   		         belong[ cities[l].belong ]--;   		         if( belong[ cities[l].belong ]==0 ) cnt--;   		         l++;	       }    	    else{     		      r++;   	    	      belong[ cities[r].belong ]++;      		      if( belong[ cities[r].belong ]==1 ) cnt++;     	   }		}		printf("Case #%d: %d\n",t,ans);	}	return 0;}

  

下面是别人过了的代码。。。T_T不知道错哪里了

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int C = 5005;const int N = 2005;const int M = 1005;int cnt[N]; //i????????int vis[C];int dp[C][2];int c, n, k, m;vector<int>v[N];struct city{    int x, y;    bool operator<(const city &a) const    {        return x<a.x;    }}ct[C];int min(int x, int y){    if(x==-1) return y;    return x<y?x:y;}void dfs(int s){    vis[s] = 1;    dp[s][1] = 1;    dp[s][0] = 0;    for(int i=0; i<v[s].size(); i++)    {        int ss = v[s][i];        if(vis[ss]==1 || cnt[ss]==0) continue;        dfs(ss);        dp[s][1] += dp[ss][0];        dp[s][0] += max(dp[ss][1], dp[ss][0]);    }}bool ok(int l, int r){    int res = 0;    memset(vis, 0, sizeof(vis));    for(int i = l; i<=r; i++)    if(vis[ ct[i].y ]==0)    {        dfs( ct[i].y );        res += max( dp[ ct[i].y ][0], dp[ ct[i].y ][1] );    }    if(res>=k) return true;    else return false;}int solve(){    int kk, l, r;    kk = l = r = 1;    cnt[ ct[1].y ]++;    int ans = -1;    while(r<=c)    {        if(kk>=k && ok(l, r))        {            ans = min(ans, ct[r].x - ct[l].x);            cnt[ ct[l].y ]--;            if( cnt[ ct[l].y ]==0 ) kk--;            l++;        }        else        {            r++;            cnt[ ct[r].y ]++;            if( cnt[ ct[r].y ]==1 ) kk++;        }    }    return ans;}int main(){    int t, tt=0, i, x, y;    scanf("%d", &t);    while(t--)    {        scanf("%d%d%d%d", &c, &n, &k, &m);        for(i=1; i<=n; i++) v[i].clear();        memset(cnt, 0, sizeof(cnt));        memset(vis, 0, sizeof(vis));        for(i=1; i<=c; i++) scanf("%d%d", &ct[i].x, &ct[i].y);        sort(ct+1, ct+1+c);        for(i=1; i<=m; i++)        {            scanf("%d%d", &x, &y);            v[x].push_back(y);            v[y].push_back(x);        }        printf("Case #%d: %d\n", ++tt, solve());    }	return 0;}

  

HDU 4354