2019.01.29【NOIP提高组】模拟B组 JZOJ 4245 san

版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/86689854

D e s c r i p t i o n Description

给定 n n 个点和 m m 条边,求经过某个点的奇数长度最短路的个数

对于50% 的数据, N 100 N ≤ 100
对于全部数据, N 1000 ; M 3000 N ≤ 1000;M ≤ 3000 ,每条路的长度不超过1000。
保证图连通,无自环重边。


S o l u t i o n Solution

这题正解是 D A G d p DAGdp 不过我们可以跑多元最短路径然后暴力找最短路即可


C o d e Code

#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;int n,m,l[1001],x,y,z,tot,path[1001],sum[1001],dis[1001];
struct node{int next,to,w;}e[6001];
bool vis[1001];
inline void add(int u,int v,int w)
{
	e[++tot]=(node){l[u],v,w};l[u]=tot;
	e[++tot]=(node){l[v],u,w};l[v]=tot;
	return;
}
inline char Getchar()
{
    static char buf[10000000],*p1=buf+10000000,*pend=buf+10000000;
    if(p1==pend)
    {
        p1=buf; pend=buf+fread(buf,1,10000000,stdin);
        if (pend==p1) return -1;
    }
    return *p1++;
}
inline long long read()
{
    char c;int d=1;long long f=0;
    while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
    while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
inline void spfa(int u)
{
	queue<int>q;
	memset(dis,0x3f3f3f3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(path,0,sizeof(path));
	dis[u]=0;q.push(u);
	while(q.size())
	{
		int x=q.front();q.pop();vis[x]=false;
		for(register int i=l[x];i;i=e[i].next)
		{
			int y=e[i].to,w=e[i].w;
			if(dis[x]+w<dis[y])
			{
				dis[y]=dis[x]+w;
				if(!vis[y]) vis[y]=true,q.push(y);
			}
		}
	}
	return;
}
inline int dfs(int x,int fa)
{
	int s=(dis[x]&1);
	for(register int i=l[x];i;i=e[i].next)
	{
		int y=e[i].to,w=e[i].w;
		if(dis[x]+w==dis[y]) s+=dfs(y,fa); 
	}
	sum[x]+=s;
	return s;
}
signed main()
{
	n=read();m=read();
	for(register int i=1;i<=m;i++) x=read(),y=read(),z=read(),add(x,y,z);
	for(register int i=1;i<=n;i++)
	{
		spfa(i);//spfa暴力计算
		dfs(i,i);//暴力找最短路
	}
	for(register int i=1;i<=n;i++) printf("%d\n",sum[i]);
}

猜你喜欢

转载自blog.csdn.net/xuxiayang/article/details/86689854
今日推荐