ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022.7.31学习笔记

2022-07-31 21:04:46  阅读:93  来源: 互联网

标签:笔记 int 31 long lsqxx dfn low ans 2022.7


主要内容:

1.最小瓶颈路
2.kruskal 重构树
3.差分约束系统
4.强连通分量
5.DFS树
6.kosaraju算法求SCC
7.tarjan算法求SCC
8.SAT问题

最小瓶颈路

模板:

#include<bits/stdc++.h>
#define re return
#define lowbit(x) (x&(-x))
#define dec(i,l,r) for(int i=l;i>=r;--i)
#define inc(i,l,r) for(int i=l;i<=r;++i)
const int maxn=1005,maxm=200005;
using namespace std;
template<typename T>inline void rd(T&x) {
    char c;
    bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

int n,m,q,deep[maxn],hd[maxn],fa[maxn],f[maxn][25],dis[maxn][25];

struct node {
    int fr,to,nt,val;
    bool operator<(node x)const {
        re val<x.val;
    }
} e[maxn<<1],e1[maxm];

inline int find(int x) {
    re x==fa[x]?x:fa[x]=find(fa[x]);
}

inline void dfs(int x,int fa) {
    deep[x]=deep[fa]+1;
    for(int i=0; f[f[x][i]][i]; ++i) {
        f[x][i+1]=f[f[x][i]][i];
        dis[x][i+1]=max(dis[x][i],dis[f[x][i]][i]);
    }
    for(int i=hd[x]; i; i=e[i].nt) {
        int v=e[i].to;
        if(v!=fa) {
            f[v][0]=x;
            dis[v][0]=e[i].val;
            dfs(v,x);
        }
    }
}

inline int LCA(int x,int y) {
    int ans=0;
    if(deep[x]<deep[y])x^=y^=x^=y;
    dec(i,24,0)
    if(deep[f[x][i]]>=deep[y]) {
        ans=max(ans,dis[x][i]);
        x=f[x][i];
    }
    if(x==y)re ans;

    dec(i,24,0)
    if(f[x][i]!=f[y][i]) {
        ans=max(ans,dis[x][i]);
        ans=max(ans,dis[y][i]);
        x=f[x][i];
        y=f[y][i];
    }
    re max(ans,max(dis[x][0],dis[y][0]));
}
int main() {

    int x,y,z;
    rd(n),rd(m);
    rd(q);
    inc(i,1,m) {
        rd(x),rd(y),rd(z);
        e1[i]=(node) {
            x,y,0,z
        };
    }

    sort(e1+1,e1+m+1);

    int cnt=0,k=0;
    inc(i,1,n)fa[i]=i;
    inc(i,1,m) {
        int x=e1[i].fr,y=e1[i].to,w=e1[i].val;
        int f1=find(fa[x]),f2=find(fa[y]);
        if(f1!=f2) {
            e[++k]=(node) {
                x,y,hd[x],w
            };
            hd[x]=k;
            e[++k]=(node) {
                y,x,hd[y],w
            };
            hd[y]=k;
            ++cnt;
            fa[f1]=f2;
            if(cnt==n-1)break;
        }
    }

    inc(i,1,n)
    if(!deep[i])dfs(i,0);
    int s,t;
    inc(i,1,q) {
        rd(s),rd(t);
        if(i==27)
            x=1;
        if(find(s)!=find(t))printf("-1\n");
        else printf("%d\n",LCA(s,t));
    }
    return 0;
}

kruskal 重构树

模板:

#include<bits/stdc++.h>
using namespace std;
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
int N = 200000;
int n,m,q;
vector<int> g[200010];
int lg2[200010];
vector<int> dep, dfn;
vector<int> stmx[200010], stmn[200010], anc[200010];
int cha[200010];
struct rec {
    int x,y,z;
} edge[500010];
bool operator<(rec a,rec b) {
    return a.z<b.z;
}
int qz[200010];
int fa[200010];
int get(int x) {
    if(fa[x]==x)return x;
    else return fa[x] = get(fa[x]);
}
int kruskal() {
    int cnt = n;
    f(i,1,2*n)fa[i]=i;
    f(i, 1, m) {
        int x = get(edge[i].x);
        int y = get(edge[i].y);
        if(x == y)continue;
        else {
            int z = ++cnt;
            g[x].push_back(z);
            g[y].push_back(z);
            g[z].push_back(x);
            g[z].push_back(y);
            fa[x]=z;
            fa[y]=z;
            qz[z] = edge[i].z;
        }
    }
    return cnt;
}
int ccnt;
void dfs(int now, int fa) {
    dfn[now] = ++ccnt;
    dep[now] = dep[fa] + 1;
    anc[now][0] = fa;
    f(i, 1, lg2[dep[now]] - 1) {
        anc[now][i] = anc[anc[now][i - 1]][i - 1];
    }
    f(i, 0, (int)g[now].size() -1 ) {
        if(g[now][i] != fa) dfs(g[now][i], now);
    }
}
int lca(int qx, int qy) {
    if(dep[qx] < dep[qy]) swap(qx, qy);
    while(dep[qx] > dep[qy]) {
        qx = anc[qx][lg2[dep[qx]-dep[qy]] - 1];
    }
    if(qx == qy) return qx;
    for(int k = lg2[dep[qx]] - 1; k >= 0; k--) {
        if(anc[qx][k] != anc[qy][k]) {
            qx = anc[qx][k];
            qy = anc[qy][k];
        }
    }
    return anc[qx][0];
}

void STmx_prework() {
    f(i, 1, n) stmx[i][0] = dfn[i];
    int mx = log(n) / log(2);
    f(j, 1, mx) {
        int mxi = n - (1 << j) + 1;
        f(i, 1, mxi) {
            stmx[i][j] = max(stmx[i][j - 1], stmx[i + (1 << (j - 1))][j - 1]);
        }
    }
}
void STmn_prework() {
    f(i, 1, n) stmn[i][0] = dfn[i];
    int mx = log(n) / log(2);
    f(j, 1, mx) {
        int mxi = n - (1 << j) + 1;
        f(i, 1, mxi) {
            stmn[i][j] = min(stmn[i][j - 1], stmn[i + (1 << (j - 1))][j - 1]);
        }
    }
}
int querymx(int l, int r) {
    int mx = log(r - l + 1) / log(2);
    int ans;
    ans = max(stmx[l][mx], stmx[r - (1 << mx) + 1][mx]);
    return ans;
}
int querymn(int l, int r) {
    int mx = log(r - l + 1) / log(2);
    int ans;
    ans = min(stmn[l][mx], stmn[r - (1 << mx) + 1][mx]);
    return ans;
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    f(i, 1, N) lg2[i] = lg2[i - 1] + (1 << lg2[i - 1] == i);
    int t;
    cin >> t;
    while(t--) {

        cin>>n>>m>>q;
        f(i, 1, m) {
            int u, v;
            cin >> u >> v;
            edge[i].x = u, edge[i].y = v, edge[i].z = i;
        }
        sort(edge+1,edge+m+1);
        f(i,1,2*n)g[i].clear();
        int root = kruskal();
        n=2*n;
        cl(dep, n+10);
        cl(dfn,n+10);
        f(i,0,n+9) {
            cl(anc[i],30);
            cl(stmx[i],30);
            cl(stmn[i],30);
        }

        dfs(root, 0);
        STmx_prework();
        STmn_prework();
        f(i,1,n) cha[dfn[i]] = i;
        f(i, 1, q) {
            int l, r;
            cin >> l >> r;
            if(l == r) {
                cout << 0 << " ";
                continue;
            }
            int mx = querymx(l, r), mn = querymn(l, r);
            int lcaa = lca(cha[mx], cha[mn]);
            cout << qz[lcaa] <<" ";
        }
        cout << endl;
    }
    return 0;
}

差分约束系统

模板:

#include<bits/stdc++.h>
using namespace std;
queue<long long>p;
long long n,m,a,b,c,bj[5005],sz[5005],cs[5005],wz;
long long ans,head[5005];
struct hehe {
    long long w,cd,syg;
} lsqxx[10005];
void add(long long t,long long w,long long cd) { 
    ans++;
    lsqxx[ans].w=w;
    lsqxx[ans].cd=cd;
    lsqxx[ans].syg=head[t];
    head[t]=ans;
}
bool qg() {
    for(int i=1; i<=n; i++) {
        sz[i]=1000;
    }
    while(p.empty()==false) {
        wz=p.front();
        bj[wz]=0;
        p.pop();
        for(int i=head[wz]; i!=0; i=lsqxx[i].syg) {
            if(sz[lsqxx[i].w]>sz[wz]+lsqxx[i].cd) { 
                sz[lsqxx[i].w]=sz[wz]+lsqxx[i].cd;
                if(bj[lsqxx[i].w]==0) {
                    bj[lsqxx[i].w]=1;
                    cs[lsqxx[i].w]++;
                    if(cs[lsqxx[i].w]==n) { 
                        return false;
                    }
                    p.push(lsqxx[i].w);
                }
            }
        }
    }
    return true;
}
int main() {
    cin>>n>>m;
    for(int i=1; i<=n; i++) {
        add(0,i,0);
    }
    for(int i=0; i<m; i++) {
        cin>>a>>b>>c;
        add(b,a,c);
    }
    p.push(0);
    if(qg()==false) { 
        cout<<"NO"<<endl;
    } else {
        for(int i=1; i<=n; i++) { 
            cout<<sz[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

强连通分量

模板:

#include<bits/stdc++.h>
using namespace std;
const int N=300002;
map<string,int> a;
int ver[N],next[N],head[N];
int dfn[N],low[N],s[N],ins[N],c[N];
int tot,cnt,idx,top;
void add(int x,int y) {
    ver[++tot]=y;
    next[tot]=head[x];
    head[x]=tot;
}

void tarjan(int x) {
    dfn[x]=low[x]=++idx;
    s[++top]=x;
    ins[x]=1;
    for(int i=head[x]; i; i=next[i]) {
        int y=ver[i];
        if(dfn[y]==0) {
            tarjan(y);
            low[x]=min(low[y],low[x]);
        } else if(ins[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(dfn[x]==low[x]) {
        cnt++;
        while(1) {
            c[s[top]]=cnt;
            ins[s[top]]=0;
            if(s[top--]==x) break;
        }
    }
}
int main() {
    int n,m ;
    scanf("%d",&n);
    string s1,s2;
    for(int i=1; i<=n ; i++) {
        cin>>s1>>s2;
        a[s1]=i;
        a[s2]=i+n;
        add(i,i+n);
    }
    scanf("%d",&m );
    for(int i=1; i<=m ; i++) {
        cin>>s1>>s2;
        add(a[s2],a[s1]);
    }
    for(int i=1; i<=n*2; i++) {
        if(dfn[i]==0)
            tarjan(i);
    }
    for(int i=1; i<=n; i++) {
        if(c[i]==c[i+n]) puts("Unsafe");
        else puts("Safe");
    }
    return 0;
}

DFS树

模板:

不讲

kosaraju算法求SCC

模板(核心):

inline void dfs(int k)
{
    f[k]=0;
    for (int i=0;i<a[k].size();++i)
    if (f[a[k][i]]) dfs(a[k][i]);
    s.push_back(k);
}
inline void rdfs(int k)
{
    f[k]=0;
    c[k]=tot;
    t[tot]++;
    for (int i=0;i<b[k].size();++i)
    if (f[b[k][i]]) rdfs(b[k][i]);
}

tarjan算法求SCC

模板:

#include <bits/stdc++.h>
using namespace std;
const int maxn=10010;
struct edge {
    int to;
    edge(int to_) {
        to=to_;
    }
};
vector<edge> gpe[maxn];
int dfn[maxn],low[maxn],ins[maxn],scc[maxn],size[maxn],cnt=0,sccn=0;
stack<int> s;
void tarjan(int u) {
    dfn[u]=low[u]=++cnt;
    s.push(u);
    ins[u]=1;
    for(int i=0; i<gpe[u].size(); i++) {
        int v=gpe[u][i].to;
        if(!dfn[v]) {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        } else if(ins[v]) {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]) {
        ins[u]=0;
        scc[u]=++sccn;
        size[sccn]=1;
        while(s.top()!=u) {
            scc[s.top()]=sccn;
            ins[s.top()]=0;
            size[sccn]+=1;
            s.pop();
        }
        s.pop();
    }
    return;
}
int n,m,oud[maxn];
int main(void) {
    scanf("%d %d",&n,&m);
    memset(low,0x3f,sizeof(low));
    memset(ins,0,sizeof(ins));
    for(int i=1; i<=m; i++) {
        int u,v;
        scanf("%d %d",&u,&v);
        gpe[u].push_back(edge(v));
    }
    for(int i=1; i<=n; i++) {
        if(!dfn[i]) {
            cnt=0;
            tarjan(i);
        }
    }
    for(int u=1; u<=n; u++) {
        for(int i=0; i<gpe[u].size(); i++) {
            int v=gpe[u][i].to;
            if(scc[u]!=scc[v]) oud[scc[u]]++;
        }
    }
    int cont=0,ans=0;
    for(int i=1; i<=sccn; i++) {
        if(oud[i]==0) {
            cont++;
            ans+=size[i];
        }
    }
    if(cont==1) {
        printf("%d",ans);
    } else {
        printf("0");
    }
    return 0;
}

SAT问题

模板:

#include<bits/stdc++.h>
#define LL long long
LL in() {
    char ch;
    LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    return x * f;
}
const int maxn = 2e6 + 100;
struct node {
    int to;
    node *nxt;
    node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
    void *operator new(size_t) {
        static node *S = NULL, *T = NULL;
        return (S == T) && (T = (S = new node[1024]) + 1024), S++;
    }
};
node *head[maxn];
bool ins[maxn];
int st[maxn], top, bel[maxn], cnt, n, m, tot;
int dfn[maxn], low[maxn];
void add(int from, int to) {
    head[from] = new node(to, head[from]);
}
void tarjan(int x) {
    dfn[x] = low[x] = ++tot;
    ins[st[++top] = x] = true;
    for(node *i = head[x]; i; i = i->nxt) {
        if(!dfn[i->to]) {
            tarjan(i->to);
            low[x] = std::min(low[x], low[i->to]);
        } else if(ins[i->to]) low[x] = std::min(low[x], dfn[i->to]);
    }
    if(dfn[x] == low[x]) {
        cnt++;
        do {
            bel[st[top]] = cnt;
            ins[st[top]] = false;
            top--;
        } while(st[top + 1] != x);
    }
}
bool judge() {
    for(int i = 1; i <= n; i++) printf("i = %d, bel = [%d,%d]\n", i, bel[i], bel[i + n]);
    for(int i = 1; i <= n; i++) if(bel[i] == bel[i + n]) return true;
    return false;
}
int main() {
    n = in(), m = in();
    int x, y, xx, yy;
    for(int i = 1; i <= m; i++) {
        x = in(), xx = in(), y = in(), yy = in();
        if(xx && yy) add(x + n, y), add(y + n, x);
        if(xx && !yy) add(x + n, y + n), add(y, x);
        if(!xx && yy) add(x, y), add(y + n, x + n);
        if(!xx && !yy) add(x, y + n), add(y, x + n);
    }
    for(int i = 1; i <= n << 1; i++) if(!dfn[i]) tarjan(i);
    if(judge())    printf("IMPOSSIBLE\n");
    else {
        printf("POSSIBLE\n");
        for(int i = 1; i <= n; i++)
            printf("%d%c", bel[i] < bel[i + n]? 1 : 0, i == n? '\n' : ' ');
    }
    return 0;
}

 

再见

标签:笔记,int,31,long,lsqxx,dfn,low,ans,2022.7
来源: https://www.cnblogs.com/boranhoushen/p/16538067.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有