八数码

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mst(s,_s) memset(s, _s, sizeof(s))
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int N = 1e6+100;
int T,n,m;

int bfs(string state)
{
   
	int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
	unordered_map<string,int>d;
	d[state]=0;
	queue<string>q;
	q.push(state);

	while(q.size())
	{
		auto t=q.front();
		q.pop();
	   
		if(t=="12345678x") return d[t];
		int pos=t.find('x');
		int x=pos/3,y=pos%3;
		for(int i=0;i<4;i++)
		{
			string ns=t;
			int nx=x+dx[i],ny=y+dy[i];
			if(nx<0 || nx>=3 || ny<0 || ny>=3) continue;

			int n_pos=nx*3+ny;
			swap(ns[pos],ns[n_pos]);
			if(d.count(ns)) continue;
			d[ns]=d[t]+1;
			q.push(ns);
			
		}
	}
	return -1;
}



int main() {
	string s;
	for(int i=0;i<9;i++)
	{
		char t;
		cin>>t;
		s=s+t;
	}
	cout<<bfs(s)<<endl;
	return 0;
}

树的重心

思路

​ dfs枚举:

  • 枚举哪个点被删去
  • dfs可以统计子树大小
  • 然后各种去max
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010, M = N * 2;

int n;
int h[N], e[M], ne[M], idx;
int ans = N;
bool st[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int _u;
int dfs(int u)
{
   st[u]=1;
   int sum=0;
   int maxv=0;
   for(int i=h[u];~i;i=ne[i])
   {
       int j=e[i];
       if(st[j]) continue;
       int k=dfs(j);
       sum+=k;
       maxv = max(maxv,k);
   }
   sum++;
   maxv = max(maxv,n-sum);
   
   if(maxv < ans)
   {
       ans=maxv;
     
       _u=u;
   }
   
   return sum;
}

int main()
{
    scanf("%d", &n);

    memset(h, -1, sizeof h);

    for (int i = 0; i < n - 1; i ++ )
    {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b), add(b, a);
    }

    dfs(1);

    printf("%d\n", ans);

    return 0;
}

有向图的拓扑序列

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
queue<int>q;
int in[N];
int n,m;
int e[N],h[N],ne[N],idx;

void add(int a,int b){
    e[idx]=b;
    ne[idx]=h[a];
    h[a]=idx++;
}
void tp_sort(){
    vector<int>res;
    for(int i=1;i<=n;i++)
        if(in[i]==0)
            q.push(i);
    while(q.size()){
        int t=q.front();
        q.pop();
        res.push_back(t);
        for(int i=h[t];i!=-1;i=ne[i]){
            int j=e[i];
            in[j]--;
            if(in[j]==0) q.push(j);
        }
    }

    if(res.size()==n)
        for(int i=0;i<res.size();i++)
            cout<<res[i]<<' ';
    else cout<<"-1";
    cout<<endl;
}

int main(){
    memset(h,-1,sizeof h);
    cin>>n>>m;
    while(m--){
        int a,b;
        cin>>a>>b;
        add(a,b);
        in[b]++;
    }
    tp_sort();
    return 0;
}

最短路(稠密图):最短路系列,在中间st,bfs前面st

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 510;

int n, m;
int g[N][N];
int dist[N];
bool st[N];
int dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i=0;i<n-1;i++)
    {
        int t=-1;
        for(int j=1;j<=n;j++)
            if(!st[j] && (t==-1 || dist[t]>dist[j]))
                t=j;
        st[t]=1;
        
        for(int j=1;j<=n;j++)
            dist[j]=min(dist[j],dist[t]+g[t][j]);
    }
    if(dist[n]>=0x3f3f3f3f/2) return -1;
    return dist[n];
}

int main()
{
    scanf("%d%d", &n, &m);

    memset(g, 0x3f, sizeof g);
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);

        g[a][b] = min(g[a][b], c);
    }

    printf("%d\n", dijkstra());

    return 0;
}

稀疏图

#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include<vector>
using namespace std;

typedef pair<int, int> pll;

const int N = 1e6 + 10;

int n, m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}


int dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    priority_queue<pll,vector<pll>,greater<pll> >q;
    q.push({0,1});
    while(q.size())
    {
        auto t=q.top();
        q.pop();
        
        int ver=t.second,distance=t.first;
      
        if(st[ver]) continue;
        st[ver]=true;
        for(int i=h[ver];~i;i=ne[i])
        {
            int j=e[i];
            if(dist[j]>w[i]+distance)
            {
                dist[j]=w[i]+distance;
                q.push({dist[j],j});
            }
        }
    }
    if(dist[n]>=0x3f3f3f3f) return -1;
    return dist[n];
}
int main()
{
    scanf("%d%d", &n, &m);

    memset(h, -1, sizeof h);
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }

    cout << dijkstra() << endl;

    return 0;
}

spfa判负环

#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
int h[N],ne[N],w[N],e[N],idx;
void add(int a,int b,int c)
{
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}
int n,m,dis[N],st[N],cnt[N];
bool spfa()
{
    memset(dis,0x3f,sizeof dis);
    queue<int>q;
    for(int i=1;i<=n;i++)
    {
        q.push(i);
        st[i]=1;
        
    }
    while(q.size())
    {
        int t=q.front();
        q.pop();
        st[t]=0;
        for(int i=h[t];~i;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                cnt[j]=cnt[t]+1;
                if(cnt[j]>=n) return true;
                if(!st[j])
                {
                    q.push(j);
                    st[j]=1;
                }
            }
        }
    }
    return false;
}
int main()
{
    cin>>n>>m;
    memset(h,-1,sizeof h);
    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    if(spfa()) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    return 0;
}

克鲁斯卡尔 最小生成树

#include<bits/stdc++.h>
using namespace std;
const int N=2e6;
int n,m;
int f[N];
struct node{
    int a,b,w;
    bool operator<(const node &t)const{
        return w<t.w;
    }
}edges[N];
int find(int x)
{
    return x==f[x]?x:f[x]=find(f[x]);
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int a,b,w;
        cin>>a>>b>>w;
        edges[i]={a,b,w};
    }
    int cnt=0,res=0;
    sort(edges,edges+m);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=0;i<m;i++)
    {
        int a=edges[i].a,b=edges[i].b,w=edges[i].w;
        a=find(a),b=find(b);
        if(a!=b)
        {
            f[a]=b;
            res+=w;
            cnt++;
        }
    }
    if(cnt<n-1) cout<<"impossible"<<endl;
    else cout<<res<<endl;
    return 0;
}

二分图最大匹配

#include <cstring>
#include <iostream>
using namespace std;

const int N = 510, M = 1e5 + 10;
int n1, n2, m;
int e[M], ne[M], h[N], idx;
bool st[N];
int match[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
bool find(int x)
{
    for(int i=h[x];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(!st[j])
        {
            st[j]=1;
            if(!match[j]||find(match[j]))
            {
                match[j]=x;
                return true;
            }
        }
    }
    
    return 0;
}

int main()
{
    scanf("%d%d%d", &n1, &n2, &m); 
    memset(h, -1, sizeof h);
    while (m--)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b);
    }
    int res = 0;
    for (int i = 1; i <= n1; i++)  // 给每个新郎找女票。
    {
        memset(st, false, sizeof st); // 给每个新娘都盖上盖头。
        if (find(i)) res++;     // 如果找到一对,就成一对。看看最后最多能成多少对?
    }
    printf("%d\n", res);
}


 posted on 2020-08-14 10:23  谁是凶手1703  阅读(72)  评论(0)    收藏  举报