2019暑假集训8.22(problem3.chess)
作者:互联网
第一问每个点八个方向连边后(敌军点边权为0,空点边权为1)用dijkstra跑一下就行。
主要是第二问,难点在于只是走的空点不同才能算作不同的路。
如:
只能算作一条路径。
于是考虑建新图,重新连边,白点(空点)直接和相邻的白点相连
注意!如图中1,2号点,可能存在两个白点之间有多个黑点,而这时候只能连一条边,不然最短路计数时会多计,在连边的时候打上vis标记即可
处理方式是:对于每一个点都去看与它相连的边。
#include<bits/stdc++.h> #define N 52 #define INF 9000000000000000000 #define inf 2100000000 #define LL long long using namespace std; int read() { int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } struct EDGE{ int nextt,to,val; }w[N*N*N*N]; struct EdgeE{ int nextt,to; }w2[N*N*N*N]; struct qnode{ int v,c; qnode(int _v=0,int _c=0):v(_v),c(_c){} bool operator <(const qnode &r)const {return r.c<c;} }; int ud[]={1,1,-1,-1,2,2,-2,-2},lr[]={2,-2,2,-2,1,-1,1,-1}; int sx,sy,ex,ey,sord,eord,n,m; int mp[N][N],head[N*N],head2[N*N],xu[N][N],dis[N*N],vis[N*N],vv[N*N],kong[N*N]; LL dep[N*N],num[N*N]; LL ans=INF; int ge=0,rua=0,rua2=0; LL tot=0; void add(int a,int b,int c) { rua++; w[rua].nextt=head[a]; w[rua].to=b; w[rua].val=c; head[a]=rua; } void add2(int a,int b)//建新图 { rua2++; w2[rua2].nextt=head2[a]; w2[rua2].to=b; head2[a]=rua2; } void init() { for(int x=1;x<=m;++x) for(int y=1;y<=n;++y) for(int i=0;i<8;++i) { int xx=x+lr[i],yy=y+ud[i]; if(xx>=1&&xx<=m&&yy>=1&&yy<=n&&mp[xx][yy]!=2)//八个方向连边 add(xu[x][y],xu[xx][yy],(mp[xx][yy]!=1&&mp[xx][yy]!=4)); } } void dij(int s,int t)//跑最短路 { priority_queue<qnode>q; for(int i=1;i<=ge;++i)dis[i]=inf; dis[s]=0; q.push(qnode(s,0)); while(!q.empty()) { int x=q.top().v;q.pop(); if(vis[x])continue; vis[x]=1; for(int i=head[x];i;i=w[i].nextt) { int v=w[i].to; if(!vis[v]&&dis[v]>dis[x]+w[i].val) { dis[v]=dis[x]+w[i].val; q.push(qnode(v,dis[v])); } } } } void dfs(int x,int last)//每个点都去连边,只连一层 { for(int i=head[x];i;i=w[i].nextt) { int v=w[i].to; if(kong[v]||v==eord) { if(!vv[v]){vv[v]=1;add2(last,v);continue;} } else dfs(v,last); } } /*void dfs(int root,int rt) { if(rt==sord&&root!=rt) return; if(kong[rt]&&rt!=root) {add2(root,rt);return;} for(int i=head[rt];i;i=w[i].nextt) { int v=w[i].to; if(!vv[v]) vv[v]=1,dfs(root,v); } }*/ void ways(int s,int t)//最短路计数 { queue<int>que; memset(vis,0,sizeof(vis)); num[s]=1;vis[s]=1;que.push(s); while(!que.empty()) { int x=que.front();que.pop(); for(int i=head2[x];i;i=w2[i].nextt) { int v=w2[i].to;//printf(">>%d\n",v); if(!vis[v])dep[v]=dep[x]+1,num[v]=num[x],vis[v]=1,que.push(v); else if(dep[v]==dep[x]+1)num[v]=(num[v]+num[x]); } } printf("%lld\n",num[t]); } int main() { // freopen("chess.in","r",stdin); // freopen("chess.out","w",stdout); m=read(),n=read(); for(int i=1;i<=m;++i) for(int j=1;j<=n;++j) { mp[i][j]=read(); xu[i][j]=++ge; if(mp[i][j]==0||mp[i][j]==3)kong[ge]=1; int x=mp[i][j]; if(x==3)sx=i,sy=j,sord=xu[sx][sy]; else if(x==4)ex=i,ey=j,eord=xu[ex][ey]; } init(); dij(sord,eord); printf("%d\n",dis[eord]); for(int i=1;i<=n*n;++i) if(kong[i])memset(vv,0,sizeof(vv)),dfs(i,i); ways(sord,eord); } /* 4 5 0 0 0 0 1 0 0 3 0 0 0 0 0 4 0 0 1 0 0 0 */View Code
标签:rt,&&,int,problem3,vis,num,2019,8.22,que 来源: https://www.cnblogs.com/yyys-/p/11402043.html