1. 程式人生 > >通信網絡

通信網絡

正常的 循環 return false 反向連接 但是 tac 鄰接表 tor

超時,60

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector> 
#include<string>
#include<queue>
#include<map>
#include<stack>
using namespace std; 
const int maxn = 10005 ;
int d[1005][1005];         //d[i][j]=1  表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識       
                        
//d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 bool vis[1005]; //vis[i]=true 表示具有所有d[x][i]=1的部門 int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) { vis[i] = false; for(int j=1;j<=n;j++) { if(i!=j) d[i][j] = 0
; else d[i][j] = 1; } } for(int i=1;i<=m;i++) { int u,v; scanf("%d %d",&u,&v); d[u][v] = 1; //d[i][j]=1 表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識 ,可傳遞 d[v][u] = 2; //d[i][j]=2 表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 ,不可傳遞
} for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { if(d[k][i]==1 && i!=k) { queue<int> q; q.push(k); while(!q.empty()) { int temp = q.front(); q.pop(); for(int j=1;j<=n;j++) { if(d[j][temp] == 1 && j!=temp) { d[j][i] = 1; if(d[i][j]!=1) d[i][j] = 2; if(vis[j] == false) { vis[j] = true; q.push(j); } } } } } } } int ans = 0,i,j; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(d[i][j] == 0) break; } if(j==n+1) ans++; } cout<<ans; return 0; }

超時,80

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector> 
#include<string>
#include<queue>
#include<map>
#include<stack>
using namespace std; 
const int maxn = 10005 ;
int d[1005][1005];         //d[i][j]=1  表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識       
                        //d[i][j]=2  表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 
                        
bool vis[1005];            //vis[i]=true 表示具有所有d[x][i]=1的部門 
bool used[1005];        
struct EDGE
{
    int u,v;
}e[10005];        //節省時間,不必通過2個for循環尋找d[i][j]=1的邊 

//通過e數組和vis 節省時間 

int main()
{
    int n,m; 
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        vis[i] = false;
        for(int j=1;j<=n;j++)
        {
            if(i!=j)    d[i][j] = 0;
            else        d[i][j] = 1;
        }        
    }                
        
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&e[i].u,&e[i].v);
        d[e[i].u][e[i].v] = 1;            //d[i][j]=1  表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識       ,可傳遞 
        d[e[i].v][e[i].u] = 2;            //d[i][j]=2  表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門       ,不可傳遞 
    }
    
    int u,v;
    for(int k=1;k<=m;k++)
    {
        u = e[k].u;
        v = e[k].v;
         
        if(vis[u] == true)            //說明所有d[x][u]=1的點都已經找到,不需要回溯
        {
            for(int j=1;j<=n;j++)
            {
                if(d[j][u] == 1 && j!=u)
                {
                    d[j][v] = 1;
                    if(d[v][j]!=1)
                        d[v][j] = 2; 
                } 
            }
            continue; 
        } 
        
        for(int j=1;j<=n;j++)
            used[j]=false;        //false表示此次回溯中還沒用過的點,防止雙向回路死循環(用dfs,bfs特別註意), 
        
        
        queue<int> q;            //v向前回溯,尋找所有d[x][v]=1的點, 
        q.push(v);                //先尋找所有d[x][v]=1的點,再逐級往前推,bfs 
        used[v] = true; 
        while(!q.empty())                //錯誤點:死循環,有雙向回路的時候 
        {
            int temp = q.front();        //第一次是v,第二次是使d[x][v]=1的x 
            q.pop();
            for(int j=1;j<=n;j++)
            {
                if(d[j][temp] == 1 && j!=temp)
                {
                    d[j][v] = 1;
                    if(d[v][j]!=1)
                        d[v][j] = 2; 
                    if(vis[temp] == true)        //說明所有d[x][temp]=1的點都已經找到,隊列不需要繼續添加temp前面的j 
                        continue;
                        
                    if(used[j] == true)            //頂點j已經參與回溯過 
                        continue;
                            
                    q.push(j);
                    used[j] = true;
                } 
            }        
        }
        vis[v] = true;        //通過回溯具有了所有d[x][v]=1的信息,x不一定與v直接連接 
        
    }
    int ans = 0,i,j;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(d[i][j] == 0)
                break;
        }
        if(j==n+1)    ans++;
    }
    cout<<ans;
    return 0;
}

編譯錯誤

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector> 
#include<string>
#include<queue>
#include<map>
#include<stack>
using namespace std; 
int first[10005],next[10005]; 
int d[1005][1005];         //d[i][j]=1  表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識 ,
                        //d[i][j]=2  表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門 
bool vis[1005];            //vis[i]=true 表示具有所有d[x][i]=1的部門 
bool used[1005];        
struct EDGE
{
    int u,v;
}e[10005];         

//通過e數組節省時間,不必通過2個for循環尋找d[i][j]=1的邊
//通過vis數組節省時間,不必重復回溯 
//通過鄰接表節省時間,u已知, 不必通過循環找到所有d[x][u]=1的點, 通過鄰接表(反向連接) 
int main()
{
    int n,m; 
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        vis[i] = false;
        for(int j=1;j<=n;j++)
        {
            if(i!=j)    d[i][j] = 0;
            else        d[i][j] = 1;
        }        
    }                
    for(int i=1;i<=m;i++)
    {
        first[i] = -1;
        next[i] = -1;
    }
    
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&e[i].u,&e[i].v);
        d[e[i].u][e[i].v] = 1;            //d[i][j]=1  表示i部門知道j部門的存在並且j部門和所有d[x][i]=1的部門認識       ,可傳遞 
        d[e[i].v][e[i].u] = 2;            //d[i][j]=2  表示i部門和j部門相互認識,但是j部門無法認識i部門之前的部門       ,不可傳遞 
        
        next[i] = first[e[i].v];    //反向連接 ,2->1,3->1,e數組存儲的還是正常的路徑順序,u=2,v=1 ;u=3,v=1 
        first[e[i].v] = i;            //但是通過鄰接表連起來的順序是 1->2->3,   
    }
    
    /*
    for(int i=1;i<=n;i++)
    {
        int num = first[i];
        while(num!=-1)
        {
            cout<<e[num].u<<" "<<e[num].v<<endl;
            num = next[num];
        }
        cout<<endl;
    }*/
    
    int u,v,j;
    for(int k=1;k<=m;k++)
    {
        u = e[k].u;
        v = e[k].v;
         
        if(vis[u] == true)            //說明所有d[x][u]=1的點都已經找到,不需要回溯,只需要使所有d[x][v]=1 
        {
            j = first[u];        //每個e[j]都是類似 x->->->u 這樣的邊        
            while(j!=-1)
            {
                d[e[j].u][v] = 1;
                if(d[v][e[j].u]!=1)
                    d[v][e[j].u] = 2; 
                j = next[j];
            }
            continue; 
        } 
        
        for(j=1;j<=n;j++)
            used[j]=false;        //false表示此次回溯中還沒用過的點,防止雙向回路死循環(用dfs,bfs特別註意), 
        
        
        queue<int> q;            
        q.push(v);                //尋找所有d[x][v]=1的點,x------>v
        used[v] = true;         //編號為v的頂點已經使用 
        
        while(!q.empty())                //錯誤點:死循環,有雙向回路的時候 
        {
            int temp = q.front();         
            q.pop();
            j = first[temp];        
            while(j!=-1)
            {
                //找到所有d[x][temp]=1的點,令d[x][v] = 1; 
                //每個e[j] 都是 x->->temp 的邊, 
                 
                d[e[j].u][v] = 1;
                if(d[v][e[j].u]!=1)
                    d[v][e[j].u] = 2; 
                
                if(vis[temp] == true)        //說明所有d[x][temp]=1的點都已經找到,隊列不需要繼續添加temp前面的j 
                {
                    j = next[j];
                    continue; 
                }    
                    
                if(used[e[j].u] == true)            //頂點e[j].u已經使用過 
                {
                    j = next[j];
                    continue; 
                }            
                q.push(e[j].u);
                used[e[j].u] = true;
                j = next[j];
            }
                    
        }
        vis[v] = true;        //通過回溯具有了所有d[x][v]=1的信息,x不一定與v直接連接 
        
    }
    int ans = 0,i;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(d[i][j] == 0)
                break;
        }
        if(j==n+1)    ans++;
    }
    cout<<ans;
    return 0;
}

通信網絡