最短路相关

最短路计数都会吧都会吧都会吧(yousiki&&zhoutb行为)(狗头 逃:)

反正我不会,估计你们都会:),放个板子

cnt[1] = 1,dis[1] = 0;
while(!q.empty()){
	int x = q.top().front;
	q.pop();
	if(vis[x]) continue;
	vis[x] = true;
	for(int i = head[x];i;i = next[i]){
		int y = to[i];
		if(dis[y] == dis[x] + w[i]) cnt[y] += cnt[x];
		if(dis[y] > dis[x] + w[i]){
			dis[y] = dis[x] + w[i];
			cnt[y] = cnt[x];
			if(!vis[y]) q.push(make_pair(-dis[y],y));
		}
	}
}

P1144 最短路计数 裸

//千万不要交我的代码 滑稽 
#include<con>
#include<iostream>
#include<vector>
#include</dev/console> 
#include<queue>
using namespace std;
const int maxn = 0x3f3f3f3f;
int n, m, x, y;
int vis[1000010],dis[1000010], ans[1000010]; //ans存最短路个数
vector<int> g[1000010];
queue<int> q;
inline void spfa(int x)
{
    for(int i=1; i<=n; i++)dis[i] = maxn;
    q.push(x);
    vis[x] = 1;
    ans[x] = 1; // 本身为1个最短路
    dis[x] = 0;
    while (!q.empty())
        {
            u = q.front();
            q.pop();
            for (int i = 0; i < g[u].size(); i++)
                {
                    v = g[u][i];
                    if (dis[v] > dis[u] + 1) //如果满足u到v的距离比原本到v的距离小,则更新
                        {
                            dis[v] = dis[u] + 1;
                            ans[v] = ans[u]; // v点和u点在一条路上,所以v的最短路个数等于u的最短路个数
                            if (!vis[v])
                                vis[v] = 1, q.push(v);
                        }
                    else if (dis[v] == dis[u] + 1)
                        ans[v] = (ans[v] + ans[u]) % 100003; // 该点最短路个数为u最短路个数+v最短路个数
                }
            vis[u] = 0;
        }
}
int main()
{
    std::cin >> n >> m;
    while (m--)
        {
            cin >> x >> y;
            g[x].push_back(y),g[y].push_back(x);
        }
    spfa(1);
    for (int i = 1; i <= n; i++)
        cout << ans[i] << endl;
    return 0;
}

CF 37E

给定一幅n*m的黑白图,现在要求在全白图里进行染色,每次能把一块四联通快染成同一种颜色,问至少需要几次才能和给定图染得一样

从目标图开始将图染成初始图,对于直接相邻的两个格子连边,如果颜色相同,则权值为0,反之为1,然后在图上跑最短路,显然对于每个单位距离,我们都要重新染色一次,所以答案即为从某一个点出发最远距离的最小值 + 1(注意:如果终态染成了全黑的图,因为初始图是全白,所以代价 + 1

#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#define maxn 100
#define inf 0x3f3f3f3f
using namespace std;
int n,m,ans = inf;
char s[maxn][maxn];	
int dis[15000],vis[15000],head[15000],cnt = 0;
struct edge{
	int to,next,w;
}e[15000<<1];
void add(int u,int v,int w){
	e[++cnt].to = v;
	e[cnt].w = w;
	e[cnt].next = head[u];
	head[u] = cnt;
}
int zb(int x,int y){return (x-1)*m+y;}
void spfa(int ss){
	queue<int>q;
	memset(dis,0x3f,sizeof(dis));
	dis[ss] = 0;
	q.push(ss);
	vis[ss] = 1;
	while(!q.empty()){
		int u = q.front();
		q.pop(); vis[u] = 0;
		for(int i =head[u];i;i = e[i].next){
			int v = e[i].to;
			if(dis[v] > dis[u] + e[i].w){
			dis[v] = dis[u] + e[i].w;
			if(vis[v] == 0) vis[v] = 1,q.push(v);
		}}
	}
	int tmp=-1; 
     for(int i=1;i<=n*m;i++){
         if(s[(i-1)/m+1][(i-1)%m+1] == 'B')tmp = std::max(tmp,dis[i]+1);
         else tmp = std::max(tmp,dis[i]);
     }
     ans = std::min(ans,tmp);
}
int main(){
	std::cin>>n>>m;
	for(int i = 1;i <= n;i ++)
		for(int j = 1;j <= m;j++)
			std::cin>>s[i][j];
	for(int i = 1;i <= n;i++)
		for(int j = 1;j <= m;j++){
			if(i>1)add(zb(i,j),zb(i-1,j),(s[i][j]!=s[i-1][j]));
			if(i<n)add(zb(i,j),zb(i+1,j),(s[i][j]!=s[i+1][j]));
			if(j>1)add(zb(i,j),zb(i,j-1),(s[i][j]!=s[i][j-1]));
			if(j<m)add(zb(i,j),zb(i,j+1),(s[i][j]!=s[i][j+1]));
		}
	for(int i = 1;i <= n * m;i++) spfa(i);
	std::cout<<ans;
}
posted @ 2020-07-27 21:43  INFP  阅读(70)  评论(0编辑  收藏  举报