NOIP2014部分题解

Day 1:

联合权值:

= =好嘛 我承认这道题我也不造什么算法。。就跟着思路做呗
#include
#include
#include
using namespace std;
const int maxn=200005;
const int mod=10007;
struct edge
{
	int to,next;
}e[maxn*2];
typedef long long ll;
int n;
int u,v;
int k=0;
ll w[maxn];
ll s[maxn];
ll maxx[maxn],sb[maxn];
ll ans1,ans2;
ll head[maxn];
void init()//文件操作 
{
	freopen("link.in","r",stdin);
	freopen("link.out","w",stdout);
}
void add(int u,int v)//建边 
{
	k++;
	e[k].to=v;
	e[k].next=head[u];
	head[u]=k;
}
void work()
{
	for(int i=1;i<=n;i++)
	{
		int p=head[i];
		while(p!=0)//>=0
		{
			int p1=e[p].to;
			s[i]+=w[p1];
			if(w[p1]>=maxx[i])
			{
				sb[i]=maxx[i];
				maxx[i]=w[p1];
			}
			else if(w[p1]>sb[i])
			{
				sb[i]=w[p1];
			}
			p=e[p].next;
		}
		ans1=max(ans1,maxx[i]*sb[i]);
	}
	for(int i=1;i<=n;i++)
	{
		int p=head[i];
		while(p!=0)//>=0
		{
			int p1=e[p].to;
			ans2+=w[p1]*(s[i]-w[p1]);
			ans2%=mod;
			p=e[p].next;
		}
		
	}
}
int main()
{
	init();
	scanf("%d",&n);
	for(int i=1;i

Day 2:

wireless

= =直接枚举一遍就是了。。
#include
#include
#include
using namespace std;
const int maxn=600;
int d;
int n;
int x,y,k;
int w[maxn][maxn];
int hehe=0;
int ans=0;
void init()
{
	freopen("wireless.in","r",stdin);
	freopen("wireless.out","w",stdout);
}
int point(int x,int y)//以当前点为中心 
{
	int sum=0;
	for(int i=x-d;i<=x+d;i++)
	{
		for(int j=y-d;j<=y+d;j++)
		{
			if(i>=0&&j>=0)
			{
				sum+=w[i][j];
			}
		}
	}
	return sum;
}
int main()
{
	init();
	scanf("%d",&d);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d %d %d",&x,&y,&k);
		w[x][y]=k;
	}
	for(int i=0;i<=128;i++)
	{
		for(int j=0;j<=128;j++)
		{
			int sb=point(i,j);
			if(sb>ans)
			{
				ans=sb;
				hehe=1;
			}
			else if(ans==sb) hehe++;
		}
	}
	printf("%d %d",hehe,ans);
	return 0;
}

/*
1
2
4 4 10
6 6 20
*/

Road

最开始的时候建立反向边,然后从终点dfs一遍,将不能到的点筛掉,如果不能到达起点则直接输出-1,然后再建立正向边,用spfa进行最短路查询。
#include//spfa+dfs
#include
#include
using namespace std;
const int maxn=10005;
const int maxm=200005;
const int inf=0x7f7f7f;

struct edge
{
	int to,next;
}e[maxm*2];
int n,m;
int k,head[maxn];
bool visit[maxn];
bool used[maxn];
bool sb[maxn];
int a[maxm],b[maxm];
int queue[maxn];
int dist[maxn];
int s,t;

void add(int u,int v)
{
	k++;
	e[k].to=v;
	e[k].next=head[u];
	head[u]=k;
}
void init()
{
	freopen("road.in","r",stdin);
	freopen("road.out","w",stdout);
}
void dfs(int t)//先反向搜一次,如果一直未访问该点,则表示不与终点联通,直接输出-1 
{
	if(used[t]) return;
	used[t]=true;
	int p=head[t];
	while(p!=0)
	{
		int p1=e[p].to;
	//	printf("p1=%d\n",p1);
		if(!used[p1]) dfs(p1);
		p=e[p].next;
	}
}
void spfa(int s,int t)
{
	memset(dist,inf,sizeof(dist));
	int qhead=0,tail=1;
	dist[s]=0;
	sb[s]=true;
	queue[tail]=s;
	while(qheaddist[p]+1&&visit[e[p1].to])//spfa只走vis=true的点
			{
				dist[e[p1].to]=dist[p]+1;
				if(!sb[e[p1].to])
				{
					tail++;
					queue[tail]=e[p1].to;
					sb[e[p1].to]=true;
				}
			}
			p1=e[p1].next;
		}
	}
	printf("%d\n",dist[t]);
}
int main()
{
	init();
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++)
    {
    	scanf("%d %d",&a[i],&b[i]);
    	add(b[i],a[i]);
    }
    scanf("%d %d",&s,&t);
    dfs(t);
    if(!used[s]) printf("-1\n");//1次筛选 
    else//重置 
    {
    	
    	memset(e,0,sizeof(e));
    	memset(head,0,sizeof(head));
    	for(int i=1;i<=m;i++)
    	{
    		add(a[i],b[i]);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if(used[i]) visit[i]=true;
    		int p=head[i];
    		while(p!=0)
    		{
    			int p1=e[p].to;
    			if(!used[p1]) visit[i]=false;
    			p=e[p].next;
    		}
    	}
		spfa(s,t);
    }
	return 0;
}
/*
3 2
1 2
2 1
1 3


6 6
1 2
1 3
2 6
2 5
4 5
3 4
1 5
*/


你可能感兴趣的:(NOIP)