模板整理(總結別人的及自己的,每週更新)

一、二分圖

1.二分圖最大匹配(匈牙利算法模板):

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define MAX 510
using namespace std;
int map[MAX][MAX];
int v1,v2;
int visit[MAX];
int l[MAX];
bool dfs(int x)///查找匹配
{
    int i;
    for(i=1;i<=v2;i++)
    {
        if(map[x][i]&&!visit[i])
        {
            visit[i]=1;
            if(l[i]==0||dfs(l[i]))
            {
                l[i]=x;
                return true;
            }
        }
    }
    return false;
}
int nmath()///計算匹配數
{
    int i,ans=0;
    for(i=1;i<=v1;i++)
    {
        memset(visit,0,sizeof(visit));
        if(dfs(i))
            ans++;
    }
    return ans;
}
int main()
{
    int k,m,n,i,j,ans;
    while(~scanf("%d",&k)&&k)
    {
        memset(map,0,sizeof(map));
        memset(l,0,sizeof(l));
        scanf("%d%d",&n,&m);
        v1=n,v2=m;
        while(k--)
        {
            scanf("%d%d",&i,&j);
            map[i][j]=1;
        }
          ans=nmath();
        printf("%d\n",ans);
    }
    return 0;
}

2.二分圖的最大帶權匹配代碼:

#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define MAX 110
#define inf 1<<30
using namespace std;
bool s[MAX],t[MAX];///s,t,代表左右兩個集合的點是否被訪問
int w[MAX][MAX];//權值
int lx[MAX],ly[MAX];//lx,ly代表左右兩個集合中的點的頂標
int lef[MAX];///右邊點的左邊匹配點
int slack[MAX];//鬆弛度
int N[MAX],n;//N代表本來的價值(對於本體而言的)
bool dfs(int x)//深搜找增廣路
{
    int i;
    s[x]=true;
    for(i=1;i<=n;i++)
    {
        if(!t[i])
        {
            int d=lx[x]+ly[i]-w[x][i];///鬆弛量
            if(d==0)
            {
                t[i]=true;
                if((!lef[i])||dfs(lef[i]))
                {
                    lef[i]=x;
                    return true;
                }
            }
            else
            {
                slack[i]=min(slack[i],d);
            }
        }
    }
    return false;
}
void update()///更新頂標值
{
    int i,d=inf;
    for(i=1;i<=n;i++) if(!t[i])
        d=min(d,slack[i]);
    for(i=1;i<=n;i++)
    {
        if(s[i])
        {
            lx[i]-=d;
        }
    }
    for(i=1;i<=n;i++)
    {
        if(t[i])
        {
            ly[i]+=d;
        }
        else
            slack[i]-=d;
    }
}
void init()//初始化
{
    int i,j;
    memset(lef,0,sizeof(lef));
    memset(ly,0,sizeof(ly));
    for(i=1;i<=n;i++)
    {
        for(j=1,lx[i]=0;j<=n;j++)
        {
            lx[i]=max(lx[i],w[i][j]);//頂標初始化爲權值的最大的
        }
    }

}
int KM()
{
    int i,j;
    init();
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            slack[j]=inf;;
        }///初始化鬆弛度
        while(1)
        {
            for(j=1;j<=n;j++)
            {
                s[j]=t[j]=0;
            }
            if(dfs(i))///找到退出
                break;
            else
                update();///更新頂標值
        }
    }
    int result=0;
    for(i=1;i<=n;i++)
    {
        if(lef[i]>0)
        {
            result+=w[lef[i]][i];///計算和()
        }
    }
    return result;
}
int main()
{
    int i,j,x,ans;
    while(~scanf("%d",&n)&&n)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&N[i]);
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf("%1d",&x);
                x==1?w[i][j]=N[i]^N[j]:w[i][j]=0;
            }
        }
        ans=KM();
        printf("%d\n",ans);
    }
    return 0;
}

3.最小路徑覆蓋數=G的點數-最小路徑覆蓋中的邊數=|G|-最大匹配數;

4、最大團 = 補圖的最大獨立集

5、最小覆蓋數+最大獨立集 = 頂點數

6、在二分圖中 最小覆蓋數 = 最大匹配數

                                                                                                     ************************************更新日期2014.11.3


二、網絡流

 

1、最短增廣路算法(Dinic算法(白書)

代碼:
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include<queue>
#include <stdio.h>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define N 200010
#define inf 0x3f3f3f3f
using namespace std;
struct Edge
{
    int from,to,cap,flow;
};
struct Dinic
{
    int n,m,s,t;
    vector<Edge>edges;////邊集
    vector<int>G[N];///鄰接表
    bool vis[N];///訪問標誌
    int d[N];///距離
    int cur[N];///當前討論的弧
    bool bfs()///分層次得到層次圖
    {
        memset(vis,0,sizeof(vis));
        queue<int>Q;
        Q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!Q.empty())
        {
            int x=Q.front();
            Q.pop();
            for(int i=0; i<G[x].size(); i++)
            {
                Edge &e=edges[G[x][i]];
                if(!vis[e.to]&&e.cap>e.flow)
                {
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int dfs(int x,int a)///增廣
    {
        if(x==t||a==0)
            return a;
        int flow=0,f;
        for(int &i=cur[x]; i<G[x].size(); i++)
        {
            Edge &e=edges[G[x][i]];
            if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
            {
                e.flow+=f;
                edges[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(!a)
                    break;
            }
        }
        return flow;
    }
    int Maxflow(int s,int t)
    {
        this->s=s;
        this->t=t;
        int flow=0;
        while(bfs())
        {
            memset(cur,0,sizeof(cur));
            flow+=dfs(s,inf);
        }
        return flow;
    }
    void addedge(int from,int to,int cap)///加邊
    {
        edges.push_back((Edge)
        {
            from,to,cap,0
        });
        edges.push_back((Edge)
        {
            to,from,0,0
        });
        m=edges.size();
        G[from].push_back(m-2);///正弧
        G[to].push_back(m-1);///反弧
    }
};
int main()
{
    Dinic D;
    int n,m,i,a,b,w;
    while(~scanf("%d%d",&n,&m))
    {
        D.s=0,D.t=n+1;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&a,&b);
            D.addedge(D.s,i,a);
            D.addedge(i,D.t,b);
        }
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&w);
            D.addedge(a,b,w);
            D.addedge(b,a,w);
        }
        cout<<D.Maxflow(D.s,D.t)<<endl;
    }
    return 0;
}


三、圖的連通性(強連通分量)

    1、tarjan算法模板(HDU 1269)
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#define N 10010
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
vector<int> G[N];
int dfn[N],low[N],st[N];///inst[N];
int t=0,top=0;
bool inst[N];
int scc_num;
void dfs(int x)
{
    low[x]=dfn[x]=(t);
    t++;
    st[top++]=x;
    inst[x]=true;
    for(int i=0;i<G[x].size();i++)
    {
        int j=G[x][i];
        if(!dfn[j])
        {
            dfs(j);
            low[x]=min(low[x],low[j]);
        }
        else if(inst[x])
        {
            low[x]=min(low[x],dfn[j]);
        }
    }
    if(low[x]==dfn[x])
    {
        scc_num++;
        while(top)
        {
           int j=st[top];
           top--;
           inst[j]=false;
           if(j==x)
                break;
        }
    }
}
void tarjan(int n)
{
    scc_num=top=t=0;
    memset(dfn,0,sizeof(dfn));
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
            dfs(i);
    }
}
int main()
{
    int n,m,i,a,b;
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            G[a].push_back(b);
        }
        tarjan(n);
        if(scc_num<=1)
            printf("Yes\n");
        else
            printf("No\n");
        for(i=0;i<=n;i++)
            G[i].clear();
    }
    return 0;
}

四、數論

1、大整數取模(a*b mod m)

    時間複雜度:O(log n)

 代碼:

LL mul_mod(LL a,LL b,LL m)
{
    LL s=0;
    while(b)//乘法變加法
    {
        if(b&1)
            s=(s+a)%m;
        a=(a*2)%m;
        b=b>>1;
    }
    return s<0?s+m:s;
}

 2、快速冪取模(a^b mod m)

    時間複雜度:O(log n)

  代碼:

    

LL pow_mod(LL a,LL b,LL m)
{
    LL res,t;
    res=1%m;
    t=a%m;
    while(b)
    {
        if(b&1)
        {
            res=mul_mod(res,t,m);///避免超 long long 
        }
        t=mul_mod(t,t,m);
        b>>=1;
    }
    return res<0?(res+m):res;
}

3、擴展歐幾里得算法(a*x+b*y=gcd(a,b))

   時間複雜度:O(logb)

代碼:

LL ext_gcd(LL a,LL b,LL &x,LL &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    LL g=ext_gcd(b,a%b,x,y);
    LL t=x;
    x=y;
    y=t-(a/b)*y;
    return g;
}

矩陣快速冪:
<pre name="code" class="cpp">struct Matrix
{
    long long int m[N][N];
    friend Matrix operator*(Matrix &a,Matrix &b)
    {
        int i,j,k;
        Matrix c;
        memset(c.m,0,sizeof(c.m));
        for(i=0; i<N; i++)
        {
            for(j=0; j<N; j++)
            {
                for(k=0; k<N; k++)
                {
                    if(!b.m[k][j]||!b.m[i][k])continue;
                    c.m[i][j]+=(a.m[i][k]*b.m[k][j]+mod)%mod;
                    c.m[i][j]%=mod;
                }
            }
        }
        return c;
    }
    friend Matrix operator^(Matrix a,int n)
    {
        Matrix b;
        memset(b.m,0,sizeof(b.m));
        for(int i=0; i<N; i++)b.m[i][i]=1;
        while(n)
        {
            if(n&1) b=b*a;
            a=a*a;
            n/=2;
        }
        return b;
    }
};

五、最短路

 1、floyd 算法(鄰接矩陣)

struct Edge
{
    int from,to,w;
};
struct Floyd
{
    int n,m;
    vector<Edge>edges;
    vector<int>G[N];
    int d[N][N];
    void init(int n)
    {
        this->n=n;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i==j)
                    d[i][j]=0;
                else
                    d[i][j]=inf;
            }
        }
    }
    void addedges(int from,int to,int w)
    {
        if(d[from][to]==inf)
        d[from][to]=w;
        else
            d[from][to]=min(d[from][to],w);
    }
    void floyd()
    {
        int k,j,i;
        for(k=0; k<n; k++)
        {
            for(i=0; i<n; i++)
            {
                for(j=0; j<n; j++)
                {
                    if(d[i][j]>(d[i][k]+d[k][j]))
                    {
                        d[i][j]=d[i][k]+d[k][j];
                    }
                }
            }
        }
    }
};


六、基礎幾何

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<stdlib.h>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<math.h>
#define inf 0x3f3f3f3f
#define eps 1e-5
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
using namespace std;
int dcmp(double x)///精度比較函數
{
    if(fabs(x)<eps)
        return 0;
    return x<0?-1:1;
}
struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {}//構造函數
    friend istream& operator >>(istream &in,Point  &A)///輸入點函數重載
    {
        /// double x,y;
        scanf("%lf%lf",&A.x,&A.y);
        return in;
    }
    friend Point operator +(Point A,Point B)//點加法
    {
        return Point(A.x+B.x,A.y+B.y);
    }
    friend Point operator -(Point A,Point B)//點減法
    {
        return Point(A.x-B.x,A.y-B.y);
    }
    friend Point operator *(Point A,double p)//點乘數
    {
        return Point(A.x*p,A.y*p);
    }
    friend Point operator /(Point A,double p)//點除數
    {
        return Point(A.x/p,A.y/p);
    }
    friend bool operator <(const Point &a,const Point &b)//點比較
    {
        return a.x<b.x||(a.x==b.x&&a.y<b.y);
    }
    friend bool operator == (const Point &a,const Point &b)///判斷點相等
    {
        return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
    }
};
typedef Point Vector;
double Dot(Vector A,Vector B)///點乘
{
    return A.x*B.x+A.y*B.y;
}
double Length(Vector A)///求向量的模
{
    return sqrt(Dot(A,A));
}
double Angle(Vector A,Vector B)///求向量的夾角
{
    return acos(Dot(A,B)/Length(A)/Length(B));
}
double Cross(Vector A,Vector B)///叉乘
{
    return A.x*B.y-A.y*B.x;
}
double Area2(Point A,Point B,Point C)///有向面積*2
{
    return Cross(B-A,C-A);
}
Vector Rotate(Vector A,double rad)//向量旋轉
{
    return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)///求兩直線的交點(法向式方程)
{
    Vector u=P-Q;
    double t=Cross(w,u)/Cross(v,w);
    return P+v*t;
}
Point getD(Point A,Point B,Point C)///uva11178
{
    Vector v1=C-B;
    double a1=Angle(A-B,v1);
    v1=Rotate(v1,a1/3);
    Vector v2=B-C;
    double a2=Angle(A-C,v2);
    v2=Rotate(v2,-a2/3);
    return GetLineIntersection(B,v1,C,v2);
}
int main()
{
    int t;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            Point A,B,C,D,E,F;
            cin>>A>>B>>C;
            D=getD(A,B,C);
            E=getD(B,C,A);
            F=getD(C,A,B);
            printf("%.6f %.6f %.6f %.6f %.6f %.6f\n",D.x,D.y,E.x,E.y,F.x,F.y);
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章