191002图论---金华

CodeForces 295B

给出\(n\)个点的有向图和一个排列,按照排列顺序删除有向图中的点, 输出每次删除后两点间最短路之和。
\(n≤ 500\)

sol:

把逐个删除转换成逐个加点,每增加一个点就用Floyd更新一下最短路。

NOI 2007 社交网络

给定 \(n\) 个点 \(m\)条边的无向图,定义 \(C_{s,t}\)\(s\)\(t\) 的最短路条数,\(C_{s,t}(u)\) 为经过 \(u\)\(s\)\(t\) 的最短路条数。对于每个节点 \(u\),求 \(I(u) =\frac{\sum_{s,t} C_{s,t}(u)}{C_{s,t}}\)
\(n≤ 100\)

sol:

Floyd。对于\(C_{s,t}\),设\(f[k][i][j]\)\(i\)\(j\)的最短路条数,每次\(dis\)数组变小时重置,相等时\(+1\)。对于\(C_{s,t}(u)\),再维护个变量在\(dis\)更新时随之更新即可。

一道例题

给定 \(n\) 个点 \(m\) 条边的无向图,每走一步所有边的边权会从 \(w\) 变成 \(\frac1{1−w}\),求 1 到 n 的最短路。 \(1 ≤n,m≤ 5000\)

sol:

手玩一下易得\(w\)变三次就变回来了,所以构建一个三层的图。记\((k,x)\)为第\(k\)层中的\(x\)点,原本\(u\)\(v\)的边就变为\((1,u)\)\((2,v)\)的边等以此类推。

World Finals 2011 H Mining Your Own Business

给定 \(n\) 个点 \(m\) 条边的无向图,你要标关键点,使得删去任意一个点后,其他所有点都能到达至少一个关键点。 最小化关键点个数,并求出最小的方案数。 复杂度要求线性。

sol:

经典题。按点双缩点建圆方树,若整个图都是个点双,易得答案为2;否则每个叶子点双都必须设一个关键点,其他点双内的点因为至少有两种路径到叶子,所以没必要设关键点。计数就只要把每个叶子点双内的点数乘起来即可。

UOJ Goodbye Jiawu B

给定 \(n\) 个点 \(m\) 条边的无向图,求哪些点删掉之后这个图会变成一棵树。 复杂度要求线性。

sol:

首先不能删割点。其次就爆删度数为\(m-n+2\)的节点就完事了。

BJOI 2013 压力

给定 \(n\) 个点 \(m\) 条边的无向图,每次操作将 \(u\),\(v\) 之间所有必须经过的点 权值加一,求操作完了之后每个点的权值。 \(n≤ 10^5,m,q≤ 2×10^6\)

sol:

建圆方树。每次必经的点一定是割点,也就是圆方树中的圆点,于是考虑树上差分。

POI 2012 Festival

\(n\) 个变量 \(m\) 个条件,每个形如 \(x_i = x_j + 1\)\(x_i ≤x_j\),求所有变量不同 取值个数的最大值。 \(n≤ 600\)

sol:

对于每个形如\(x_i = x_j + 1\) 的式子可以转化为\(x_i\leq x_j+1\)\(x_j\leq x_i-1\)。建出差分约束图,考虑用Tarjan缩点,易得任意两个强连通分量之间取值都不会重复。现在的问题就简化为每个强连通分量里可以有多少个取值。因为每条边连接的两个点之间的差值不会超过\(1\),所以它们的取值一定在整数上连续,故取值个数为最长路长度\(+1\)。最终答案即为每个强连通分量的答案之和。

SCOI 2011 糖果

\(n\) 个变量 \(m\) 个条件,每个形如 \(x_i = x_j\)\(x_i ≤x_j\)\(x_i ≥x_j\)\(x_i < x_j\)\(x_i > x_j\),求和最小的非负整数解。 \(n,m≤ 10^5\)

sol:

\(x_i = x_j\)可转化为\(x_i\leq x_j\)\(x_j\leq x_i\)\(x_i < x_j\)\(x_i > x_j\)也类似转化成小于等于的形式。缩点,有一个性质就是图中没有正权边,所以每一个强连通分量里的边必定全是零。那就只要按拓扑序逆序一遍递推即可。

NOI 2017 游戏

小 L 计划进行\(n\)场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏。
小 L 的赛车有三辆,分别用大写字母A、B、C表示。地图一共有四种,分别用小写字母\(x,a,b,c\)表示。其中,赛车A不适合在地图\(a\)上使用,赛车B不适合在地图\(b\)上使用,赛车C不适合在地图\(c\)上使用,而地图\(x\)则适合所有赛车参加。适合所有赛车参加的地图并不多见,最多只会有\(d\)张。小 L 对游戏有一些特殊的要求,这些要求可以用四元组 \((i, h_i, j, h_j)\)来描述,表示若在第\(i\)场使用型号为\(h_i\) 的车子,则第\(j\)场游戏要使用型号为\(h_j\) 的车子。如果有多种方案,输出任意一种,如果无解,输出 \(-1\)

sol:

这题唯一的难点就在于有一种适合三种地图的赛车。但很快就会发现这其实是假的,因为这种地图只有\(8\)张,所以只要枚举这种地图用A车或B车,用B车或C车。这样其实就已经涵盖了所有情况。复杂度\(O(N\times 2^d)\)

#include 
using namespace std;
const int N=200005;
int n,d,m,px[N],gn,dfn[N],low[N],st[N],top,cnt,num,col[N];
char p[N],tmp='\0';bool vis[N];
struct node{int x,y;char c1,c2;} game[N];
vector ver[N];
inline int turn(int x,char c){
    switch(p[x]){
        case 'a':return c=='B'?0:c=='C'?1:2;
        case 'b':return c=='A'?0:c=='C'?1:2;
        case 'c':return c=='A'?0:c=='B'?1:2;
    }
    return 2;
}
inline char out(int x,int y){
    switch(p[x]){
        case 'a':return y?'B':'C';
        case 'b':return y?'A':'C';
        case 'c':return y?'A':'B';
    }
    return 'X';
}
inline void tarjan(int x){
    dfn[x]=low[x]=++cnt;st[++top]=x;vis[x]=1;
    for(int i=0;id){sol();return;}
    p[px[x]]='a';dfs(x+1);
    p[px[x]]='b';dfs(x+1);
    p[px[x]]='x';
}
int main(){
    scanf("%d%d%s%d",&n,&d,p,&m);d=0;
    for(int i=0;i<=n;i++){
        swap(tmp,p[i]);
        if(p[i]=='x') px[++d]=i;
    }
    for(int i=1;i<=m;i++){
        int x,y;char c1[5],c2[5];
        scanf("%d%s%d%s",&x,c1,&y,c2);
        if(p[x]=='x'||p[y]=='x'){
            game[++gn].c1=c1[0];game[gn].c2=c2[0];
            game[gn].x=x;game[gn].y=y;continue;
        }
        link(x,y,c1[0],c2[0]);
    }
    dfs(1);printf("-1");return 0;
}

你可能感兴趣的:(191002图论---金华)