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
原文地址:https://www.cnblogs.com/Cw-trip/p/4726644.html