zoukankan      html  css  js  c++  java
  • hiho一下!

    1032 最长回文子串

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=1e6+3000;
    char r[maxv];
    char s[maxv*2];
    int p[maxv*2];
    int n;
    int len;
    void manacher(){
        s[0]='&';
        for(int i=0;i<len;i++){
            s[2*i+1]='#';
            s[2*i+2]=r[i];
        }
        s[2*len+1]='#';
        s[2*len+2]='*';
        int mx=0,mxid=0;
        for(int i=1;i<=2*len;i++){
            if(mx>i){
                p[i]=min(p[mxid*2-i],mx-i);
            }else{
                p[i]=1;
            }
            for(;s[i-p[i]]==s[i+p[i]];p[i]++);
            if(p[i]+i>mx){
                mx=p[i]+i;
                mxid=i;
            }
        }
    }
    int main(){
    ///    freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n;
        while(n--){
            scanf("%s",r);
            len=strlen(r);
            manacher();
            int ans=0;
            for(int i=1;i<=2*len;i++){
                ans=max(ans,p[i]);
            }
            cout<<ans-1<<endl;
        }
        return 0;
    }
    View Code

    1014 Trie

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int csize=26;
    const int maxv=1e5+3000;
    struct Node{
        Node *ch[csize];
        int val;
        int num;
    }pool[maxv*3];
    int ph=0;
    Node *newNode(){
        for(int i=0;i<csize;i++){
            pool[ph].ch[i]=NULL;
        }
        pool[ph].val=pool[ph].num=0;
        return &pool[ph++];
    }
    Node *root=newNode();
    void insert(Node *n,char *s,int len){
        for(int i=0;i<len;i++){
            if(n->ch[s[i]-'a']==NULL) n->ch[s[i]-'a']=newNode();
            n=n->ch[s[i]-'a'];
        }
        n->val++;
    }
    void dfs(Node *n){
        n->num=n->val;
        for(int i=0;i<csize;i++){
            if(n->ch[i]==NULL) continue;
            dfs(n->ch[i]);
            n->num+=n->ch[i]->num;
        }
    }
    int query(Node *n,char *s,int len){
        for(int i=0;i<len;i++){
            if(n->ch[s[i]-'a']==NULL) return 0;
            n=n->ch[s[i]-'a'];
        }
        return n->num;
    }
    int n;
    char r[maxv];
    int main(){
    //    freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n;
        for(int i=0;i<n;i++){
            scanf("%s",r);
            int len=strlen(r);
            insert(root,r,len);
        }
        dfs(root);
        int q;
        cin>>q;
        for(int i=0;i<q;i++){
            scanf("%s",r);
            int len=strlen(r);    
            printf("%d
    ",query(root,r,len));
        }
        return 0;
    }
    View Code

     1015 KMP(大白模板

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    using namespace std;
    typedef long long ll;
    //typedef pair<ll,ll> P;
    const int maxv=1e6+3000;
    char P[maxv];
    char T[maxv];
    int fail[maxv];
    void getFail(char *P,int *f){
        int len=strlen(P);
        f[0]=f[1]=0;
        for(int i=1;i<len;i++){
            int j=f[i];
            while(j&&P[i]!=P[j]) j=f[j];
            f[i+1]=(P[i]==P[j]?j+1:0);
        }
    }
    int ans=0;
    void match(char *T,char *P,int *f){
        int n=strlen(T),m=strlen(P);
        int j=0;
        for(int i=0;i<n;i++){
            while(j&&P[j]!=T[i]) j=f[j];
            if(P[j]==T[i]) j++;
            if(j==m) ans++;
        }
    }
    int N;
    int n;
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n;
        while(n--){
            scanf("%s%s",P,T);
            ans=0;
            getFail(P,fail);
            match(T,P,fail);
            cout<<ans<<endl;
        }
        return 0;
    }
    View Code

     1036 AC自动机(大白模板

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=1e6+3000;
    const int csize=26;
    int ch[maxv*4][csize];
    int val[maxv*4];
    int sz=0;
    void Tclear(){
        sz=1;
        memset(ch[0],0,sizeof ch[0]);
    }
    void insert(char *s,int v){
        int u=0,n=strlen(s);
        for(int i=0;i<n;i++){
            int c=s[i]-'a';
            if(!ch[u][c]){
                memset(ch[sz],0,sizeof ch[sz]);
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]=v;
    }
    int f[maxv*4];
    int last[maxv*4];
    queue<int> Q;
    void getFail(){
        f[0]=0;
        for(int c=0;c<csize;c++){
            int u=ch[0][c];
            if(u){
                f[u]=0;
                Q.push(u);
            }
        }
        while(!Q.empty()){
            int r=Q.front();Q.pop();
            for(int c=0;c<csize;c++){
                int u=ch[r][c];
                if(!u) continue;
                Q.push(u);
                int v=f[r];
                while(v&&!ch[v][c]) v=f[v];
                f[u]=ch[v][c];
            }
        }
    }
    bool find(char *T){
        int n=strlen(T);
        int j=0;
        for(int i=0;i<n;i++){
            int c=T[i]-'a';
            while(j&&!ch[j][c]) j=f[j];
            j=ch[j][c];
            if(val[j]) return 1;
        }
        return 0;
    }
    int N;
    char r[maxv];
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        Tclear();
        cin>>N;
        for(int i=0;i<N;i++){
            scanf("%s",r);
            insert(r,1);
        }
        getFail();
        scanf("%s",r);
        if(find(r)){
            cout<<"YES"<<endl;
        }else{
            cout<<"NO"<<endl;
        }
        return 0;
    }
    View Code

     1067 离线lca,tarjan算法(这题人名处理有点恶心。。。。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=1e5+300;
    string father[maxv],son[maxv];
    int n,m;
    set<string> S;
    map<string,int> idx;
    map<int,string> dir;
    vector<P> qu[maxv];
    vector<int> G[maxv];
    int ans[maxv];
    int fa[maxv];
    int find(int x){
        if(fa[x]==x) return x;
        return fa[x]=find(fa[x]);
    }
    void setFa(int x,int f){
        fa[find(x)]=f;
    }
    bool vis[maxv];
    void dfs(int v,int f){
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i];
            if(u==f) continue;
            dfs(u,v);
            setFa(u,v);
        }
        vis[v]=1;
        for(int i=0;i<qu[v].size();i++){
            int u=qu[v][i].fs,o=qu[v][i].se;
            if(vis[u]){
                ans[o]=find(u);
            }
        }
    }
    void init(){
        for(int i=0;i<maxv;i++){
            fa[i]=i;
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        init();
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>father[i]>>son[i];
            if(S.find(father[i])==S.end()){
                idx[father[i]]=S.size()+1;
                dir[S.size()+1]=father[i];
                S.insert(father[i]);
    
            }
            if(S.find(son[i])==S.end()){
                idx[son[i]]=S.size()+1;
                dir[S.size()+1]=son[i];
                S.insert(son[i]);
            }
            G[idx[father[i]]].pb(idx[son[i]]);
        }
        cin>>m;
        string a,b;
        for(int i=0;i<m;i++){
            cin>>a>>b;
            qu[idx[a]].pb(P(idx[b],i));
            qu[idx[b]].pb(P(idx[a],i));
        }
        dfs(1,-1);
        for(int i=0;i<m;i++){
            cout<<dir[ans[i]]<<endl;
        }
    }
    View Code

     1055 树形dp1

    题目:给和1连通的一部分节点染色,问能得到的最大权值和为多少。

    思路:树形dp,注意每个节点可以进行背包(不是题解里说的无限背包。。。明明就是01背包。。。),每个子树可以选0~m个节点,dp的顺序应该是背包容量从大到小,物品随意(容量循环在外面),如果dp方向搞反就是无限背包。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=105;
    int n,m;
    int val[maxv];
    vector<int> G[maxv];
    int dp[maxv][maxv];
    void dfs(int v,int f){
        dp[v][0]=0;
        dp[v][1]=val[v];
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i];
            if(u==f) continue;
            dfs(u,v);
            for(int j=m;j>0;j--){
                for(int k=1;k<m;k++){
                    if(j-k>0)
                    dp[v][j]=max(dp[v][j],dp[v][j-k]+dp[u][k]);
                }
            }
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d",val+i);
        }
        for(int i=0;i<n-1;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].pb(b);
            G[b].pb(a);
        }
        dfs(1,-1);
        cout<<dp[1][m]<<endl;
        return 0;
    }
    View Code

     1078 线段树的区间修改,lazy标记

    题目:更改某区间的所有数,询问区间和。

    思路:借助lazy标记维护区间,每次查询和修改经过节点时下传标记。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=1e5+300;
    struct Node{
        int l,r;
        bool lazy;
        int sum,val;
        Node *ch[2];
    }pool[maxv*5];
    int ph=0;
    Node *newNode(){
        Node *n=&pool[ph++];
        n->lazy=0;
        return n;
    }
    Node *root=newNode();
    int w[maxv];
    void build(Node *n,int l,int r){
        n->l=l,n->r=r;
        if(r-l<=1){
            n->sum=w[l];
            return;
        }
        int mid=(r+l)/2;
        n->ch[0]=newNode();
        n->ch[1]=newNode();
        build(n->ch[0],l,mid);
        build(n->ch[1],mid,r);
        n->sum=n->ch[0]->sum+n->ch[1]->sum;
        return;
    }
    void pushdown(Node *n){
        if(n->r-n->l<=1) return;
        Node *chl=n->ch[0],*chr=n->ch[1];
        if(n->lazy){
            chl->lazy=1;
            chr->lazy=1;
            chl->val=n->val;
            chr->val=n->val;
            chl->sum=(chl->r-chl->l)*n->val;
            chr->sum=(chr->r-chr->l)*n->val;
            n->lazy=0;
        }
    }
    void change(Node *n,int a,int b,int x){
        pushdown(n);
        int l=n->l,r=n->r;
        Node *chr=n->ch[1],*chl=n->ch[0];
        if(l>=b||a>=r) return;
        if(l>=a&&b>=r){
            n->lazy=1;
            n->val=x;
            n->sum=(r-l)*x;
            return;
        }
        change(chl,a,b,x);
        change(chr,a,b,x);
        n->sum=chr->sum+chl->sum;
        return;
    }
    int query(Node *n,int a,int b){
        pushdown(n);
        int l=n->l,r=n->r;
        if(l>=b||a>=r) return 0;
        if(l>=a&&b>=r) return n->sum;
        return query(n->ch[0],a,b)+query(n->ch[1],a,b);
    }
    int n;
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n;
        for(int i=0;i<n;i++){
            int ss;
            scanf("%d",&ss);
            w[i]=ss;
        }
        build(root,0,n);
        int q;
        cin>>q;
        while(q--){
            int a,b,c,d;
            scanf("%d%d%d",&a,&b,&c);
            if(a==0){
                printf("%d
    ",query(root,b-1,c));
            }else{
                scanf("%d",&d);
                change(root,b-1,c,d);
            }
        }
        return 0;
    }
    View Code

     1080 同时维护线段树的两个区间修改

    题目:两种操作分别是把某区间的数都变为某个值,以及把这个区间的值全部加x,求每次操作后询问区间和。

    思路:维护两个lazy tag,分别是加上的值和直接更改的值。写的时候出现了两个问题,一个是add值不能直接覆盖,应该采用加法,因为一个节点可能多次接受从父节点push下来的add值但是未向下push。然后最开始直接把两个值分开处理的,这样有可能一个节点同时有add和val两个标记,但是两个标记push的顺序不同,结果截然不同。实际上如果已经有val标签,那么add的值直接加到val上,如果有add的标签再加val就直接清0.这样任何时候一个节点都不会有两个标签,并且保证结果正确。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxv=1e5+300;
    struct Node{
        int l,r,len;
        int val,add,sum;
        bool lazyv,lazya;
        Node *ch[2];
    }pool[maxv*5];
    int ph=0;
    inline Node *newNode(){
        Node *n=&pool[ph++];
        n->add=n->lazya=n->lazyv=0;
        return n;
    }
    Node *root=newNode();
    int w[maxv];
    void build(Node *n,int l,int r){
        n->l=l,n->r=r,n->len=r-l;
        if(r-l<=1){
            n->sum=w[l];
            return;
        }
        Node *&chr=n->ch[1],*&chl=n->ch[0];
        chr=newNode(),chl=newNode();
        build(chl,l,(r+l)/2);
        build(chr,(r+l)/2,r);
        n->sum=chr->sum+chl->sum;
        return;
    }
    inline void pushDown(Node *n){
        if(n->len<=1) return;
        Node *chl=n->ch[0],*chr=n->ch[1];
        int add=n->add,val=n->val;
        if(n->lazya){
            n->lazya=0;
            n->add=0;
            if(chl->lazyv)
                chl->val+=add;
            else{
                chl->lazya=1;
                chl->add+=add;
            }
            if(chr->lazyv) 
                chr->val+=add;
            else{
                chr->lazya=1;
                chr->add+=add;
            }
            chr->sum+=add*chr->len;
            chl->sum+=add*chl->len;
        }
        if(n->lazyv){
            n->lazyv=0;
            chl->val=val;
            chr->val=val;
            chr->lazyv=chl->lazyv=1;
            chr->lazya=chl->lazya=0;
            chr->add=chl->add=0;
            chl->sum=chl->len*val;
            chr->sum=chr->len*val;
        }
    }
    void changea(Node *n,int a,int b,int x){
        pushDown(n);
        int l=n->l,r=n->r;
        if(l>=b||a>=r) return;
        if(a<=l&&b>=r){
            n->lazya=1;
            n->add+=x;
            n->sum+=n->len*x;
            return;
        }
        Node *chr=n->ch[1],*chl=n->ch[0];
        changea(chl,a,b,x);
        changea(chr,a,b,x);
        n->sum=chr->sum+chl->sum;
    }
    void changev(Node *n,int a,int b,int x){
        pushDown(n);
        int l=n->l,r=n->r;
        if(l>=b||a>=r) return;
        if(a<=l&&b>=r){
            n->lazyv=1;
            n->val=x;
            n->sum=n->len*x;
            return;
        }
        Node *chr=n->ch[1],*chl=n->ch[0];
        changev(chl,a,b,x);
        changev(chr,a,b,x);
        n->sum=chr->sum+chl->sum;
    }
    int query(Node *n,int a,int b){
        pushDown(n);
        Node *chl=n->ch[0],*chr=n->ch[1];
        int l=n->l,r=n->r;
        if(l>=b||a>=r) return 0;
        if(a<=l&&b>=r) return n->sum;
        return query(chl,a,b)+query(chr,a,b);
    }
    int n,m;
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n>>m;
        for(int i=0;i<n+1;i++){
            scanf("%d",&w[i]);
        }
        build(root,0,n+1);
        while(m--){
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            if(a==0){
                changea(root,b,c+1,d);
            }else{
                changev(root,b,c+1,d);
            }
            printf("%d
    ",query(root,0,n+1));
        }
        return 0;
    }
    View Code

     1183 割顶,割边

    题目:如题。

    思路:tarjan算法,利用时间戳求出每个点能够通过回边到达的最小节点,即可判断。一个特殊处理是根节点。此外,需要注意每个节点都可能会重复push,需要谨慎去重。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define bk back()
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxn=2e4+400;
    int n,m;
    vector<int> G[maxn];
    int od[maxn];
    int low[maxn];
    int clo=0;
    vector<P> ce;
    vector<int> cp;
    bool used[maxn];
    void dfs(int v,int f){
        int chn=0;
        low[v]=od[v]=++clo;
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i];
            if(u==f) continue;
            if(!od[u]){
                chn++;
                dfs(u,v);
                low[v]=min(low[v],low[u]);
                if(f==-1&&chn==2) cp.pb(v);
                if(f!=-1&&low[u]>=od[v]&&!used[v]) cp.pb(v),used[v]=1;///note:may be more than one time pushed
                if(low[u]>od[v]){
                    ce.pb(P(u,v));
                    if(u>v) swap(ce.bk.fs,ce.bk.se);
                }
            }
            else
                low[v]=min(low[v],od[u]);
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n>>m;
        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].pb(b);
            G[b].pb(a);
        }
        dfs(1,-1);
        sort(ce.begin(),ce.end());
        sort(cp.begin(),cp.end());
        for(int i=0;i<cp.size();i++){
            cout<<cp[i];
            if(i<cp.size()-1) cout<<" ";
        }
        if(!cp.size()) puts("Null");
        else puts("");
        for(int i=0;i<ce.size();i++){
            cout<<ce[i].fs<<" "<<ce[i].se<<endl;
        }
        return 0;
    }
    View Code

     1184 双连通分量

    思路: 因为low[u] == dfn[u],对(parent[u],u)来说有dfn[u] > dfn[ parent[u] ],因此low[u] > dfn[ parent[u] ] ,所以(parent[u],u)一定是一个桥,那么此时栈内在u之前入栈的点和u被该桥分割开 ,则u和之后入栈的节点属于同一个组 将从u到栈顶所有的元素标记为一个组,并弹出这些元素。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define bk back()
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxn=2e4+300;
    int n,m;
    vector<int> G[maxn];
    int stk[maxn];
    int stk2[maxn];
    int stop2=0;
    int stop=0;
    int od[maxn],low[maxn];
    int clo=0;
    vector< vector<int> > bcc;
    void dfs(int v,int f){
        stk[stop++]=v;
        int chn=0;
        low[v]=od[v]=++clo;
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i];
            if(u==f) continue;
            if(!od[u]){
                chn++;
                dfs(u,v);
                low[v]=min(low[v],low[u]);
            }else
            low[v]=min(low[v],od[u]);
        }
        if(low[v]==od[v]&&f!=-1){
            bcc.pb(vector<int>());
            while(stk[stop-1]!=v){
                stop--;
                bcc.bk.pb(stk[stop]);
            }
            bcc.bk.pb(v);
            stop--;
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n>>m;
        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].pb(b);
            G[b].pb(a);
        }
        dfs(1,-1);
        bcc.pb(vector<int>());
        while(stop>0) bcc.bk.pb(stk[--stop]);
        for(int i=0;i<bcc.size();i++) sort(bcc[i].begin(),bcc[i].end());
            int *ans=new int[n+1];
        for(int i=0;i<bcc.size();i++){
            for(int j=0;j<bcc[i].size();j++){
                ans[bcc[i][j]]=bcc[i][0];
            }
        }
        cout<<bcc.size()<<endl;
        for(int i=1;i<=n;i++){
            cout<<ans[i]<<" ";
        }
        return 0;
    }
    View Code

     1174 拓扑排序

    思路:每次删去入度为0的点。此算法可以判断有向图中是否有圈,也可进行拓扑排序,复杂度较低。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define bk back()
    #define PB pop_back
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxn=1e5+400;
    int T;
    int n,m;
    int d[maxn],del[maxn];
    vector<int> G[maxn];
    void clear(){
        for(int i=0;i<maxn;i++){
            G[i].clear();
        }
        memset(d,0,sizeof d);
        memset(del,0,sizeof del);
    }
    queue<int> Q;
    void topo(){
        for(int i=1;i<=n;i++){
            if(d[i]==0){
                Q.push(i);
            }
        }
        int cont=0;
        while(!Q.empty()){
            int v=Q.front();Q.pop();
            del[v]=1;
            cont++;
            while(!G[v].empty()&&del[G[v].bk]) G[v].PB();
            for(int i=0;i<G[v].size();i++){
                int u=G[v][i];
                if(del[u]) continue;
                d[u]--;
                if(d[u]==0) Q.push(u);
            }
        }
        if(cont<n){
            puts("Wrong");
        }else{
            puts("Correct");
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>T;
        while(T--){
            clear();
            cin>>n>>m;
            for(int i=0;i<m;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                G[a].pb(b);
                d[b]++;
            }
            topo();
        }
        return 0;
    }
    View Code

     1185 强连通分量分解,拓扑排序ordfs

    思路:分解强连通分量,然后就是树上的dp了。自己yy了一个貌似复杂度还可以的缩点方法。

    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define bk back()
    #define PB pop_back
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    const int maxn=2e4+300;
    int n,m;
    vector<int> G[maxn];
    int w[maxn];
    int clo=0;
    int stk[maxn],top=0,scc_id[maxn];
    int low[maxn],od[maxn],instk[maxn];
    int scc_w[maxn];
    int scc_num=0;
    vector<int> scc_p[maxn];
    void scc_dfs(int v){
        instk[v]=od[v]=low[v]=++clo;
        stk[top++]=v;
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i];
            if(!od[u]){
                scc_dfs(u);
                low[v]=min(low[v],low[u]);
            }else if(instk[u]){
                low[v]=min(low[v],od[u]);
            }
        }
        if(low[v]==od[v]){
            ++scc_num;
            do{
                scc_id[stk[--top]]=scc_num;
                scc_w[scc_num]+=w[stk[top]];
                instk[stk[top]]=0;
                scc_p[scc_num].pb(stk[top]);
            }while(stk[top]!=v);
        }
    }
    vector<int> nG[maxn];
    int d[maxn];
    void rebuild(){
        for(int i=1;i<=scc_num;i++){
            for(int j=0;j<scc_p[i].size();j++){
                int u=scc_p[i][j];
                for(int k=0;k<G[u].size();k++){
                    int v=G[u][k];
                    if(scc_id[v]!=scc_id[u]){
                        nG[i].pb(scc_id[v]);
                        d[scc_id[v]]++;
                    }
                }
            }
        }
    }
    queue<int> Q;
    int dp[maxn];
    void topo(){
        for(int i=1;i<=scc_num;i++){
            if(d[i]==0){
                Q.push(i);
                dp[i]=scc_w[i];
            }
        }
        while(!Q.empty()){
            int v=Q.front();Q.pop();
            for(int i=0;i<nG[v].size();i++){
                int u=nG[v][i];
                dp[u]=max(dp[u],dp[v]+scc_w[u]);
                d[u]--;
                if(d[u]==0){
                    Q.push(u);
                }
            }
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        cin>>n>>m;
        for(int i=1;i<=n;i++) scanf("%d",w+i);
        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            G[a].pb(b);
        }
        scc_dfs(1);
        rebuild();
        topo();
        int ans=0;
        for(int i=1;i<=scc_num;i++) ans=max(ans,dp[i]);
        cout<<ans<<endl;
        return 0;
    }
    View Code

     1195 高斯消元(hiho找的板子

    /*
    *@author:  Cwind
    *http://www.cnblogs.com/Cw-trip/
    */
    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    #define pb push_back
    #define PB pop_back
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define IINF (1<<29)
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    ////////////////////////////////////////////////////////
    const int MAX_N = 567;
    const int MAX_M = 1024;
    const double EPS = 1e-5;
    
    struct Answer {
      double x;
      int id;
    };
    
    Answer ans[MAX_N];
    double a[MAX_M][MAX_N];
    double b[MAX_M];
    double tmp[MAX_N];
    
    void swap_line(int i, int j) {
      memcpy(tmp, a[i], sizeof(tmp));
      memcpy(a[j], a[i], sizeof(tmp));
      memcpy(a[i], tmp, sizeof(tmp));
      swap(b[i], b[j]);
      swap(ans[i], ans[j]);
    }
    
    int Gauss(int n, int m) {
      // 处理出上三角矩阵
      for (int i = 1; i <= n; i++) {
        bool flag = false;
        for (int j = i; j <= m; j++) {  // 从第i行开始,找到第i列不等于0的行j
          if (fabs(a[j][i]) > EPS) {
            swap_line(j, i);            // 交换第i行和第j行
            flag = true;
            break;
          }
        }
        // 若无法找到,则存在多个解
        if (!flag)
          return 2;                     // 解多于一个
        // 消除第i+1行到第M行的第i列
        for (int j = i + 1; j <= m; j++)
          tmp[j] = a[j][i] / a[i][i];
        for (int j = i + 1; j <= m; j++) {
          for (int k = 1; k <= n; k++) {
            a[j][k] = a[j][k] - a[i][k] * tmp[j];
          }
          b[j] = b[j] - b[i] * tmp[j];
        }
      }
      // 检查是否无解,即存在 0 = x 的情况
      for (int i = 1; i <= m; i++) {
        if (fabs(b[i]) < EPS)
          continue;
        bool all_zero = true;           // 第i行系数均为0?
        for (int j = 1; j <= n; j++) {
          if (fabs(a[i][j]) > EPS) {
            all_zero = false;
            break;
          }
        }
        if (all_zero)
          return 0;                     // 无解
      }
      // 此时存在唯一解
      // 由于每一行都比前一行少一个系数,所以在M行中只有前N行有系数
      // 从第N行开始处理每一行的解
      for (int i = n; i >= 1; i--) {
        // 利用已经计算出的结果,将第i行中第i+1列至第N列的系数消除
        for (int j = i + 1; j <= n; j++) {
          b[i] = b[i] - a[i][j] * ans[j].x;
          a[i][j] = 0;
        }
        ans[i].x = b[i] / a[i][i];
      }
      return 1;                        // 唯一解
    }
    
    bool id_order(const Answer& a, const Answer& b) {
      return a.id < b.id;
    }
    
    //Zconst int maxn=505;
    int n,m;
    int main(){
      ///  freopen("/home/files/CppFiles/in","r",stdin);
        //freopen("/home/files/CppFiles/out","w",stdout);
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                scanf("%lf",&a[i][j]);
            }
            scanf("%lf",&b[i]);
            ans[i].id=i;
        }
        int val=Gauss(n,m);
        if(val==0){
            puts("No solutions");
        }else if(val==2){
            puts("Many solutions");
        }else{
            sort(ans+1,ans+n+1,id_order);
            for(int i=1;i<=n;i++){
                printf("%d
    ",int(ans[i].x + 0.5));
            }
        }
        return 0;
    }
    View Code

    1196 高斯消元(异或方程组//kuangbin模板

    /*
    * @author:  Cwind
    * http://www.cnblogs.com/Cw-trip/
    */
    #include <bits/stdc++.h>
    #define pb push_back
    #define se second
    #define fs first
    #define sq(x) (x)*(x)
    #define eps 0.000000001
    #define LB lower_bound
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define bk back()
    #define PB pop_back
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    
    int a[110][110];
    int x[110];
    int free_x[110];
    int free_num;
    
    //返回值为-1表示无解,为0是唯一解,否则返回自由变元个数
    int Gauss_xor(int equ,int var)
    {
        int max_r, col, k;
        free_num = 0;
        for(k = 0, col = 0; k < equ && col < var; k++, col++)
        {
            max_r = k;
            for(int i = k+1 ; i < equ; i++)
                if(abs(a[i][col]) > abs(a[max_r][col]))
                    max_r = i;
            if(a[max_r][col] == 0)
            {
                k--;
                free_x[free_num++] = col; //自由变元
                continue;
            }
            if(max_r != k)
            {
                for(int j = col; j < var+1; j++)
                    swap(a[k][j],a[max_r][j]);
            }
            for(int i = k+1; i < equ;i++)
                if(a[i][col] != 0)
                    for(int j = col; j < var+1;j++)
                        a[i][j] ^= a[k][j];
        }
        for(int i = k;i < equ;i++)
            if(a[i][col] != 0)
                return -1;
        if(k < var)return var-k;
        for(int i = var-1; i >= 0;i--)
        {
            x[i] = a[i][var];
            for(int j = i+1; j < var;j++)
                x[i] ^= (a[i][j] && x[j]);
        }
        return 0;
    }
    
    int drx[4]={1,-1,0,0};
    int dry[4]={0,0,-1,1};
    void geta(){
        for(int i=0;i<5;i++){
            for(int j=0;j<6;j++){
                a[i*6+j][i*6+j]=1;
                for(int k=0;k<4;k++){
                    int dx=i+drx[k],dy=j+dry[k];
                    if(dx>=0&&dx<5&&dy>=0&&dy<6){
                        a[i*6+j][dx*6+dy]=1;
                    }
                }
            }
        }
    }
    char r[10];
    bool grid[10][10];
    int main(){
        ////freopen("/home/files/CppFiles/in","r",stdin);
        geta();
    /*    for(int i=0;i<30;i++){
            for(int j=0;j<30;j++){
                printf("%d",a[i][j]);
            }
            puts("");
        }*/
        for(int i=0;i<5;i++){
            scanf("%s",r);
            for(int j=0;j<6;j++){
                grid[i][j]=r[j]-'0';
            }
        }
        for(int i=0;i<30;i++){
            a[i][30]=1^grid[i/6][i%6];
        }
        Gauss_xor(30,30);
        int num=0;
        for(int i=0;i<30;i++) if(x[i]) num++;
        cout<<num<<endl;
        for(int i=0;i<30;i++){
            if(x[i]){
                printf("%d %d
    ",i/6+1,i%6+1);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ado异常代码含义对照表及SQL Access,oracle 数据类型对照表
    关于同花顺日数据格式
    把自己以前的QQ plan贴一下
    为应用程序制作帮助文件
    [临时]单源最短路径(Dijkstra算法)
    [IDA] 分析for循环的汇编代码
    对 strlen 汇编代码的解释
    [VC6] 在对话框上实现LOGO图片的渐变性切换效果
    [C++]拼图游戏
    使用 ADO 向数据库中存储一张图片
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4726644.html
Copyright © 2011-2022 走看看